Стандартная библиотека четко документы how to import source files directly (учитывая абсолютный путь к файлу исходного файла), но этот подход не работает, если что исходный файл использует неявные импорт одноуровневые, как описано в примере ниже.Python 3.5+: Как динамически импортировать модуль с учетом полного пути к файлу (при наличии имплицитного импорта собора)?
Как этот пример можно адаптировать для работы при наличии имплицитных импортных товаров?
Я уже проверил this и this other StackOverflow вопросы по этой теме, но они не затрагивают импортирует неявное Sibling в файл импортируется вручную.
Установка/Пример
Вот показательный пример
Структура каталогов:
root/
- directory/
- app.py
- folder/
- implicit_sibling_import.py
- lib.py
app.py
:
import os
import importlib.util
# construct absolute paths
root = os.path.abspath(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
isi_path = os.path.join(root, 'folder', 'implicit_sibling_import.py')
def path_import(absolute_path):
'''implementation taken from https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly'''
spec = importlib.util.spec_from_file_location(absolute_path, absolute_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
isi = path_import(isi_path)
print(isi.hello_wrapper())
lib.py
:
def hello():
return 'world'
implicit_sibling_import.py
:
import lib # this is the implicit sibling import. grabs root/folder/lib.py
def hello_wrapper():
return "ISI says: " + lib.hello()
#if __name__ == '__main__':
# print(hello_wrapper())
Запуск python folder/implicit_sibling_import.py
с if __name__ == '__main__':
блока закомментированы урожайности ISI says: world
в Python 3.6.
Но работает python directory/app.py
выходы:
Traceback (most recent call last):
File "directory/app.py", line 10, in <module>
spec.loader.exec_module(module)
File "<frozen importlib._bootstrap_external>", line 678, in exec_module
File "<frozen importlib._bootstrap>", line 205, in _call_with_frames_removed
File "/Users/pedro/test/folder/implicit_sibling_import.py", line 1, in <module>
import lib
ModuleNotFoundError: No module named 'lib'
Обход
Если добавить к import sys; sys.path.insert(0, os.path.dirname(isi_path))
app.py
, python app.py
дает world
, как задумано, но я хотел бы избежать munging sys.path
, если это возможно.
требования Ответ
я хотел python app.py
печатать ISI says: world
, и я хотел бы сделать это, изменив функцию path_import
.
Я не уверен в последствиях mangling sys.path
. Например. если был directory/requests.py
, и я добавил путь к directory
в sys.path
, я бы не хотел import requests
, чтобы начать импорт directory/requests.py
вместо импорта requests library, который я установил с pip install requests
.
Решение ДОЛЖНО быть реализовано как функция python, которая принимает абсолютный путь к нужному модулю и возвращает module object.
В идеале решение не должно вводить побочные эффекты (например, если оно изменяет sys.path
, оно должно вернуть sys.path
в исходное состояние). Если решение действительно вводит побочные эффекты, оно должно объяснить, почему решение не может быть достигнуто без введения побочных эффектов.
PYTHONPATH
Если у меня есть несколько проектов, делают это, я не хочу, чтобы помнить, чтобы установить PYTHONPATH
каждый раз, когда я переключаться между ними. Пользователь должен просто иметь возможность pip install
моего проекта и запускать его без каких-либо дополнительных настроек.
-m
-m
flag является рекомендуемым/вещий подход, но стандартная библиотека явно документы How to import source files directly. Я хотел бы знать, как я могу адаптировать этот подход, чтобы справиться с неявным относительным импортом. Очевидно, что внутренние компоненты Python должны это делать, и как внутренние элементы отличаются от документации «импортировать исходные файлы напрямую»?
Что касается Python, этот «имплицитный импорт брака» является обычным абсолютным импортом и, безусловно, не является имплицитным относительным импортом. Имплицированный относительный импорт больше не поддерживается в Python 3. – user2357112
Изменение 'sys.path', вероятно, лучший выбор. Что бы вы ни делали, чтобы механизм импорта выглядел в папке этого файла, он должен задерживаться дольше первоначального импорта, поскольку функции из этого файла могут выполнять дальнейшие импортные операции при их вызове. – user2357112
@ user2357112 Действительно [PEP 8] (https://www.python.org/dev/peps/pep-0008/#imports) говорит, что относительный неявный импорт отключен на Python 3. Но мне остается интересно: если выше пример не относительный неявный импорт, то что? У вас есть пример? –