Импорт файла из другой папки в текущую папку

avatar
Aditya Shukla
1 июля 2021 в 15:40
80
1
0

Позвольте мне предварить это, сказав, что я понимаю, что импорт является часто затрагиваемой темой в сообществе Python. Я только хочу, чтобы была разработана простая система импорта, но увы. В таком виде я уже упомянул много мест для потенциальных решений; пожалуйста, проверьте в приведенных ниже параграфах ссылки на другие темы вопросов SO, которые я уже прошел.

Вот структура каталогов для моего проекта:

Directory structure

Я хочу импортировать файл1.py из папки1 папки main_folder в свой код в файле2.py.

Следовательно, код импорта в file2.py:

from main_folder.folder1.file1 import some_func

Я пытаюсь нормально запустить file2.py из каталога приложения (python main_folder/folder2/file2.py)

Я также пробовал следующие возможные решения в тех же условиях (все безрезультатно):

from application.main_folder.folder1.file1 import some_func # after adding init to application folder

и...

from folder1.file import some_func

и...

from .folder1.file1 import some_func

и...

from ..folder1.file1 import some_func

Я попробовал ответы, предложенные в этом другом вопросе. Второй по популярности ответ кажется самым питоническим способом сделать это, и я действительно пробую именно этот подход выше. Однако этот ответ, похоже, не работает для многих людей (и для меня), которые указали это в комментариях и предложили открыть еще один вопрос относительно того же.

Если этот подход не работает, то какую команду sys.path.append() следует добавить вверху файла file2.py, чтобы иметь возможность from folder1.file1 import some_func? Я понимаю, что этот метод sys.path.append не самый питонический способ сделать это, но, к сожалению, у нас, по-видимому, нет лучшего решения, пока ребята, разрабатывающие Python, не запустят что-то.

Источник

Ответы (1)

avatar
Lenormju
2 июля 2021 в 07:47
0

Возможно, вам будет интересно прочитать документацию по системе импорта Python и переменной sys.path.

При запуске программы Python инициализирует переменную sys.path на основе переменной среды PYTHONPATH. Он перечисляет каталоги, в которых он будет искать пакеты (каталоги, содержащие файл __init__.py) при импорте чего-либо.

Чтобы предотвратить конфликты импорта (и для ясности), лучше использовать имя вашего приложения в качестве пакета верхнего уровня. Это то, что вы хотите сделать, хорошо!

Но чтобы заставить from application.main_folder.folder1.file1 import some_func работать, Python должен найти пакет с именем application в одном из каталогов, перечисленных в его sys.path.

Оттуда вы либо можете убедиться, что при вызове вашей программы PYTHONPATH будет содержать каталог, содержащий ваш пакет application, либо вам придется добавить его самостоятельно, изменив sys.path.

Первое решение, как правило, проще и разумнее, потому что именно так должны работать библиотеки: поместите их в каталог, который ищет Python, и все готово, все работает!

Второе решение требует, чтобы вы гарантировали, что каким бы способом ни вызывался любой из ваших файлов, это приведет к тому, что родительский каталог вашего пакета верхнего уровня будет добавлен в sys.path (в начале или в конце, в вашем случае это не так). имеет большое значение). Вставить его только один раз чище. Но он должен быть там до того, как любая инструкция импорта будет выполнена. Как это реализовать, зависит от того, как используется ваша библиотека.

Вы говорите:

Я пытаюсь нормально запустить file2.py из каталога приложения (главная_папка python/folder2/file2.py)

В PYTHONPATH документации упоминается, что:

Дополнительный каталог будет вставлен в путь поиска перед PYTHONPATH, как описано выше в разделе Параметры интерфейса.

Если вы попросите Python запустить четыре file2.py, которые содержат import sys; print(sys.path), вы увидите, что он содержит в первой позиции путь к folder2 (C:\PycharmProjects\StackOverflow\lib68213183\main_folder\folder2 для меня).

Добавление import pathlib; sys.path.insert(0, str(pathlib.Path(__file__).parent.parent.parent.parent)) добавляет родительский каталог application к пути поиска (вы можете проверить, повторно напечатав sys.path). Теперь вы можете импортировать: from lib68213183.main_folder.folder1.file1 import say_hello; say_hello() работает.

Но если кто-то запустит вместо этого file1.py, путь не изменится (код, который это делает, находится в file2.py, который вы не можете импортировать, потому что родитель родителя родителя родителя родителя не находится в пути поиска), поэтому у вас есть сделать это и там. Вам нужно будет добавить родительский каталог вашего пакета верхнего уровня в sys.path в каждом файле, который может быть вызван из командной строки. Это немного громоздко, но если у вас их немного, может быть все в порядке.

Более простое решение — добавить файл __init__.py в каталог application (сделав его пакетом), добавив родительский каталог application в PYTHONPATH, и все готово! А если вы собираетесь распространять свой код, это тоже упростит задачу.