PEP8 - импортировать не поверх файла с sys.path
проблема
PEP8 имеет правило о вводе импорта в начало файла:
Импорт всегда помещается в верхнюю часть файла, сразу после комментариев модуля и доклингов, а также перед глобалами и константами модуля.
Однако в некоторых случаях я могу сделать что-то вроде:
import sys
sys.path.insert("..", 0)
import my_module
В этом случае pep8
командной строки pep8
мой код:
Импорт уровня модуля E402 не поверх файла
Каков наилучший способ добиться соответствия sys.path
изменениям sys.path
?
Зачем
У меня есть этот код, потому что я следую структуре проекта, приведенной в руководстве Hitchhiker для Python.
Это руководство предполагает, что у меня есть папка my_module
, отдельно от папки tests
, оба из которых находятся в одном каталоге. Если я хочу получить доступ к my_module
из tests
, я думаю, что мне нужно добавить ..
на sys.path
Ответы
Ответ 1
Часто у меня есть несколько файлов с тестами в подкаталоге foo/tests
моего проекта, а модули, которые я тестирую, находятся в foo/src
. Чтобы запустить тесты из foo/tests
без ошибок импорта, я создаю файл foo/tests/pathmagic.py
который выглядит следующим образом:
"""Path hack to make tests work."""
import os
import sys
bp = os.path.dirname(os.path.realpath('.')).split(os.sep)
modpath = os.sep.join(bp + ['src'])
sys.path.insert(0, modpath)
В каждом тестовом файле я затем использую
import pathmagic # noqa
как первый импорт. Комментарий "noqa" не позволяет pycodestyle
/pep8
жаловаться на неиспользуемый импорт.
Ответ 2
Если есть только несколько импортов, вы можете просто игнорировать PEP8 в этих строках import
:
import sys
sys.path.insert("..", 0)
import my_module # noqa: E402
Ответ 3
Существует еще одно обходное решение.
import sys
... all your other imports...
sys.path.insert("..", 0)
try:
import my_module
except:
raise
Ответ 4
Я просто боролся с подобным вопросом, и я думаю, что нашел немного более приятное решение, чем принятый ответ.
Создайте модуль pathmagic
который выполняет фактическую манипуляцию sys.path, но внесите изменения в менеджер контекста:
"""Path hack to make tests work."""
import os
import sys
class context:
def __enter__(self):
bp = os.path.dirname(os.path.realpath('.')).split(os.sep)
modpath = os.sep.join(bp + ['src'])
sys.path.insert(0, modpath)
def __exit__(self, *args):
pass
Затем в ваших тестовых файлах (или там, где вам это нужно) вы делаете:
import pathmagic
with pathmagic.context():
import my_module
# ...
Таким образом, вы не получаете никаких жалоб от flake8/pycodestyle, вам не нужны специальные комментарии, и, похоже, структура имеет смысл.
Для дополнительной аккуратности рассмотрите возможность возврата пути в блоке __exit__
, хотя это может вызвать проблемы с ленивым импортом (если вы поместите код модуля вне контекста), возможно, это не стоит того.
EDIT: Просто увидел гораздо более простой трюк в ответе на другой вопрос: добавьте assert pathmagic
под свой импорт, чтобы избежать комментария noqa
.
Ответ 5
Чтобы соответствовать pep8, вы должны указать свой путь к пути python для выполнения относительного/абсолютного импорта.
Для этого вы можете взглянуть на этот ответ: постоянно добавлять каталог в PYTHONPATH
Ответ 6
Вы уже попробовали следующее:
import sys
from importlib import import_module
sys.path.insert("..", 0)
# import module
my_mod = import_module('my_module')
# get method or function from my_mod
my_method = getattr(my_mod , 'my_method')