Относительный импорт: подпакет, импортирующий подпакет - PullRequest
0 голосов
/ 10 октября 2018

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

root/
   script.py
   package/
      __init__.py
      module1.py
      module2.py

В script.py Мне нужно импортировать метод из module1.py и запустить его.

#contents of script.py 
from package.module1 import func1

func1()

Метод в module1.py требуетМетод из module2.py.

#contents of module1.py 
from package.module2 import func2

def func1():
    func2()

if __name__ == "__main__":
     func1()

Приведенный выше код работает, если я запускаю script.py напрямую.Однако в некоторых ситуациях мне нужно запустить module1.py напрямую через crontab, и именно в этом заключается проблема.

Когда запускается cronjob, я получаю сообщение о том, что func2 не можетбыть найденным.Я могу запустить module1.py, если я изменю импорт следующим образом:

#contents of module1.py 
from module2 import func2

def func1():
    func2()

if __name__ == "__main__":
     func1()

Я могу заставить обе ситуации работать, если я добавлю оператор else в module1.py, но это выглядит так странно:

#contents of module1.py 

def func1():
    func2()

if __name__ == "__main__":
    from module2 import func2 
    func1()
else:
    from package.module2 import func2
    func1()

Как я могу сделать это более питонически?Может мне нужно как-то использовать __init__.py?Сейчас это просто пустой файл.

1 Ответ

0 голосов
/ 10 октября 2018

При запуске файла с python file.py python не ищет каталог, содержащий file для __init__.py.Это означает, что вы не можете использовать import package.module или from .module import x import.

Способ исправить это - сообщить python, что file.py является частью пакета.Это делается с помощью переключателя -m:

python -m package.module1

Так что вам не нужно исправлять свой код, вам нужно исправить команду crontab!


Это говорит: лично мне никогда не нравится запускать модули.Я бы лучше написал run_module1.py скрипт вне пакета, который просто содержит:

from package import module1
module1.func1()

Затем запустите run_module1.py вместо прямого запуска module1.py.

Я не думаю,есть веская причина хотеть запустить module1.py так, как вы делаете, и ожидаете, что он будет работать без хакерского импорта, как вы пыталисьAFAIK, нет нехакского решения этого вопроса.

...