Импорт модулей Python с разных уровней иерархии - PullRequest
0 голосов
/ 05 ноября 2018

В верхнем уровне моего git-репозитория у меня есть следующая файловая структура:

miscellaneous Dockerfiles, readme, etc
Code/
    training.py
    data/
        generate.py
        tasksets.py

Иногда я хочу импортировать модуль generate из модуля tasksets, когда я запускаю модуль tasksets в виде скрипта, поэтому tasksets включает следующий импорт:

import generate

В других случаях я хочу импортировать модуль tasksets из модуля training, поэтому training содержит следующий импорт:

import tasksets

Однако эта настройка вызывает у меня проблемы. tasksets может нормально импортировать generate, когда я запускаю tasksets как скрипт, но выдает ошибку, если я импортирую tasksets внутри training, когда я запускаю training как скрипт (я думаю, что training может не найти generate в качестве сценария в пути по умолчанию). Я пытался просмотреть все виды вопросов и ответов StackOverflow, используя файлы __init__.py, относительный импорт и т. Д. В настоящее время мой обходной путь заключается в использовании следующих строк внутри tasksets:

if __name__ == "__main__": import generate
else: from data import generate

Но это нехорошо (и моей IDE это тоже не нравится). Кто-нибудь может объяснить, как использовать правильный набор __init__.py файлов и операторов импорта, чтобы я мог импортировать generate при запуске tasksets в качестве сценария, а также импортировать tasksets при запуске training в качестве сценария?

1 Ответ

0 голосов
/ 05 ноября 2018

Вам лучше использовать классическую архитектуру модуля / пакета Python.

projectname/
    __init__.py
    __main__.py
    data/
        __init__.py
        generate.py
        tasksets.py

Чтобы использовать ваше приложение, перейдите в каталог projectname/../ (на один уровень выше projectname/) и запустите python -m projectname. Это выполнит projectname/__main__.py.


В __main__.py вы напишите что-то вроде:

from projectname.data import generate
from projectname.data import tasksets

if __name__ == '__main__':
    generate.foo()
    tasksets.bar()
  1. Вы будете использовать абсолютный путь импорта (начиная с имени вашего модуля и точки, projectname.)
  2. Вы импортируете свои подмодули из if __name__ == '__main__'
  3. __main__.py будет единственной точкой входа вашего приложения / скрипта.

В любом другом файле вы будете использовать тот же синтаксис и пути для импорта других модулей:

data/generate.py

from projectname.data import tasksets

def foo():
    print('SPAM!')
    tasksets.bar()

Что-то, что мне не очень нравится, но я не уверен, что PEP отрицают это,

В вашем projectname/__init__.py файле вы можете написать:

from projectname.data import generate
from projectname.data import tasksets

Таким образом, ваши два подмодуля будут импортированы в вашу основную область __init__.py, так что вы сможете импортировать подмодули из этой области, например

data/generate.py:

from projectname import generate

Но опять же, мне не очень нравится этот способ (потому что Явное лучше, чем неявное. )


И последнее, но не менее важное:

  • Вы также можете использовать команду python projectname/__main__.py, но я все еще рекомендую python -m projectname
  • Вы можете создать файл setup.py, используя setuptools , чтобы «установить» ваше приложение в вашей системе и просто запустить команду projectname, чтобы запустить его.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...