, Используйте абсолютный импорт:

с

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

Как этот пример можно адаптировать для работы при наличии неявного родственного импорта?

Я уже проверилэтот а такжеэтот другой Stackoverflow вопросы по теме, но они не относятся к имплицитному импортув файл импортируется вручную.

Установка / Пример

Вот иллюстративный пример

Структура каталогов:

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 как и предполагалось, но я бы хотел избежатьsys.path если возможно.

Требования к ответу

мне бы хотелосьpython app.py печататьISI says: world и я хотел бы сделать это, изменивpath_import функция.

Я не уверен в последствиях искаженияsys.path, Например. если бы былdirectory/requests.py и я добавил путь кdirectory кsys.pathЯ бы не хотелаimport requests начать импортdirectory/requests.py вместо импортабиблиотека запросов что я установил сpip install requests.

РешениеДОЛЖЕН быть реализован как функция Python, которая принимает абсолютный путь к файлу к нужному модулю и возвращаетмодульный объект.

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

PYTHONPATH

Если у меня есть несколько проектов, я не хочу помнить, чтобы установитьPYTHONPATH каждый раз, когда я переключаюсь между ними. Пользователь должен просто иметь возможностьpip install мой проект и запустить его без каких-либо дополнительных настроек.

-m

-m флаг является рекомендуемым / питоническим подходом, но стандартная библиотека также четко документируетКак импортировать исходные файлы напрямую, Я хотел бы знать, как я могу адаптировать этот подход, чтобы справиться с неявным относительным импортом. Ясно, что внутренности Python должны это делать, так чем же они отличаются от документации «импортировать исходные файлы напрямую»?

Ответы на вопрос(5)

Ваш ответ на вопрос