Я знаю обычную систему импорта Python, пакеты, __init__.py, функцию __import__ (см. В Python, как импортировать имя файла начинается с цифры ) и т. д. Я знаю классическую Как мне импортировать другие файлы Python?ответы.
Отказ от ответственности: я знаю, что следующая файловая структура не является распространенной, но иногда вам приходится быстро иметь дело с устаревшим кодом без его рефакторинга.
|
|- 1 UTILS
| |- 123myscript.py
|- 2 TESTS
| |- test.py
Как при запуске test.py импортировать 123myscript.py, не искажая sys.path.append?
Возможно ли это с importlib? Мне не удалось это сделать с помощью:
importlib.import_module("../1 UTILS/123myscript.py", package=None)
проверьте здесь stackoverflow.com/questions/67631/…
Функция importlib.import_module работает только с именами модулей в пространстве имен модулей Python. Он не принимает пути к файлам, поскольку для поиска модулей использует пути поиска модулей Python (например, sys.path). Чтобы импортировать модуль из определенного пути к файлу, вы должны использовать функции importlib.util, как показано в ответе @simon.






Я попробовал несколько подходов, но этот работает: сначала мы создаем символическую ссылку «1 UTILS/123myscript.py» -> «2 TESTS/myscript.py», затем импортируем через библиотеку importlib. Вот содержимое файла «2 TESTS/test.py»:
# File: 2 TESTS/test.py
import importlib
import pathlib
# Create symlink "1 UTILS/123myscript.py" -> "2 TESTS/myscript.py"
utils_dir = pathlib.Path(__file__).parent.with_name("1 UTILS")
myscript_path = utils_dir / "123myscript.py"
temp = pathlib.Path(__file__).with_name("myscript.py")
temp.symlink_to(myscript_path)
# Import and clean up
myscript = importlib.import_module("myscript")
temp.unlink()
# Now we can work with the `myscript` module
Другие подходы, которые я пробовал и потерпел неудачу
cd в «1 UTILS» перед импортомsys.path перед импортом.Прагматичный ответ дан в соответствующем вопросе, на который комментарий Андрио Скура дает ссылку. Действительно, он использует importlib.
В соответствии с вашим случаем это может выглядеть следующим образом. Вот, я предполагаю
123myscript.py содержит следующий код:
# Contents of `1 UTILS/123myscript.py`
def do_something():
return 42
Тогда успешный импорт 123myscript.py в test.py будет, например:
# Contents of `2 TESTS/test.py`
import importlib.util
from pathlib import Path
location = Path(__file__).parents[1] / "1 UTILS" / "123myscript.py"
spec = importlib.util.spec_from_file_location(location.stem, location)
# ^ Instead of `location.stem` (thus "123myscript"), you can use an arbitrary name
myscript = importlib.util.module_from_spec(spec)
spec.loader.exec_module(myscript)
assert myscript.do_something() == 42
Обратите внимание: я не знаю, есть ли какие-либо зависимости в 123myscript.py, что может усложнить настройку.
Взгляните на это: github.com/tortoise/aerich/blob/…