Я упомянул несколько потоков и статей, в том числе:
но не может получить желаемый результат.
Скажем, у меня есть каталог под названием "helloworld":
helloworld
|--__init__.py
|--say_hello.py
|--another_hello
|--__init__.py
|--import_hello.py
Это say_hello.py:
def hello_world():
print("Hello World!")
if __name__ == "__main__":
hello_world()
Это import_hello.py:
from .. import say_hello
say_hello.hello_world()
Я надеюсь импортировать модуль say_hello
везде, где я называю python/path/to/import_hello.py
без использования sys
модуля.
Однако теперь, когда я выполняю python/path/to/import_hello.py
, он вернет ValueError: attempted relative import beyond top-level package
, и я понятия не имею, почему он не работает.
Даже это не работает:
from helloworld import say_hello
say_hello.hello_world()
Это даст мне ModuleNotFoundError: No module named 'helloworld'
.
Вы не можете запускать скрипт из середины пакета. Когда вы это делаете, вы не используете helloworld.another_hello.import_hello
из /path/to/helloworldsparent/
, вы используете __main__
основе /path/to/helloworldsparent/helloworld/another_hello
. Таким образом, у него нет родительского пакета для import
как ..
Вы можете запустить модуль с помощью -m
:
$ python -m helloworld.another_hello.import_hello
... предполагая, helloworld
каталог helloworld
находится на вашем sys.path
(например, потому, что вы установили его в site-packages
или потому, что ваш текущий рабочий каталог является его родителем или потому, что вы настроили PYTHONPATH
).
Но более чистое решение, как правило, должно оставлять только глубокие модули и писать сценарии "точки входа" на верхнем уровне, которые выглядят следующим образом:
import helloworld.another_hello.import_hello
helloworld.another_hello.import_hello.main()
Если вы используете setuptools
(и вы действительно должны быть для чего-то достаточно сложного, чтобы обладать двумя уровнями пакетов), вы можете заставить его автоматически создавать сценарии точки входа во время установки (или во время --inplace
во время разработки). См. Раздел " Создание автоматического сценария" в документах (но вам, вероятно, потребуется прочитать и другие разделы, чтобы получить всю идею, документы довольно большие и сложные).
Я чувствую, что вы можете сначала попытаться добавить родительский путь к системному пути, а затем попытаться использовать импорт.
from sys import path as pylib
import os
pylib += os.path.abspath('..')
from helloworld import say_hello
Надеюсь, поможет !!
setuptools
. Означает ли это, что я могу оставить import_hello.py как сейчас, т.е.from .. import say_hello; say_hello.hello_world()
?from … import
будет работать, но вы обычно хотите переместить код верхнего уровня (например,say_hello.hello_world()
) в функцию, которая может быть вызвана кем-то послеimport helloworld.another_hello.import_hello
, а не после он будет запущен в первый раз, когда кто-нибудь сделает этотimport
в процессе. Другими словами, вы хотите модули, а не скрипты, внутри пакетов.