Импорт Python3 — запуск локального vs из-за несоответствия pip

#python-3.x #pip

#python-3.x #pip

Вопрос:

У меня есть небольшой pip-пакет (назовем его my_package), который я написал на python3 со следующей структурой каталогов. Меня смущает несоответствие, которое я вижу при my_package.py локальном запуске vs, когда я тестирую его, загружая его из PyPI, импортируя его в какой-то другой код, а затем запуская его.

 .
|  README.md
|  LICENSE
|  setup.py
|  build
|  dist
|  my_package
|  -- __init__.py
|  -- my_package.py
|  -- helpers
|  ---- __init__.py
|  ---- helper1.py
|  ---- helper2.py
|  ---- helper3.py
|  ---- helper4.py
  

У my_package.py меня есть следующий импорт:

 from helpers import helper1
from helpers import helper2
from helpers import helper3
from helpers import helper4
  

Очевидно, что это всего лишь имена наполнителей, но суть в том, что я пытаюсь импортировать некоторый код из каталога помощников из my_package.py скрипта.

Если бы я должен был запустить my_package.py локально мой код выполняется без каких-либо проблем — я думаю, что это ожидаемое поведение для python3. Однако, если я загружаю это в PyPI, а затем импортирую пакет, я получаю следующую ошибку:

 Traceback (most recent call last):
  File "test.py", line 1, in <module>
    import my_package
  File "/Users/fakeUser/.virtualenvs/pip-testing/lib/python3.7/site-packages/my_package/__init__.py", line 1, in <module>
    from . my_package import main_function
  File "/Users/fakeUser/.virtualenvs/pip-testing/lib/python3.7/site-packages/my_package/my_package.py", line 6, in <module>
    from helpers import helper1
ModuleNotFoundError: No module named 'helpers'
  

Чтобы решить эту проблему, я изменил импорт, my_package.py чтобы он выглядел следующим образом:

 from .helpers import helper1
from .helpers import helper2
from .helpers import helper3
from .helpers import helper4
  

Насколько я понимаю, python3 использует . , чтобы помочь разрешить относительный импорт. Это имело смысл попробовать для меня, потому что, если я бегу my_package.py , добавление . должно дать понять, что helpers каталог находится в том же каталоге, my_package.py что и . Внесение этой модификации фактически устраняет проблему с загрузкой пакета из pip, но теперь возникает следующая проблема, если я должен был запустить этот код локально:

 Traceback (most recent call last):
  File "my_package.py", line 6, in <module>
    from .helpers import helper1
ModuleNotFoundError: No module named '__main__.helpers'; '__main__' is not a package
  

Я пытаюсь понять, что здесь происходит. В частности, если бы кто-нибудь мог объяснить следующее:

  • Почему добавление . делает код несовместимым для локального использования?
  • Почему удаление . делает код несовместимым для использования из pip?

Я действительно хочу понять, почему этот импорт не работает, чтобы избежать подобных проблем в будущем.

Ответ №1:

Для начала ознакомьтесь с модулями в начале, используя следующий шаблон

 my_package
|  README.md
|  LICENSE
|  setup.py
|  build
|  dist
|  src
|  --my_package
|  ---- __init__.py
|  ---- helpers
|  ------__init__.py
|  ------ helper1.py
|  ------ helper2.py
|  ------helper3.py
|  ------helper4.py
  

На данный момент вы можете определить верхний уровень __init__.py пустым, а внутренний __init__.py — в соответствии с тем, как helperx.py он выглядит, а затем, когда вы устанавливаете модуль, вы можете вызвать helper1 соответствующим образом, например
from my_package.helpers import helper1

Комментарии:

1. Извините за отсутствие ясности в моем исходном сообщении, но у меня действительно есть init.py файлы настроены так, как вы указали; Я отредактирую исходный вопрос, чтобы включить это. Я думаю, что я действительно понял проблему, связанную с тем, как pip установит my_package как фактический пакет, тогда как запуск скрипта изнутри my_package еще не импортировал сам пакет и, следовательно, вызывает несоответствия импорта, о которых я спрашивал. Я собираюсь закрыть вопрос. Тем не менее, спасибо за ваш ответ.

2. Отлично, пожалуйста, примите / поддержите мой ответ, если он вам помог 🙂

Ответ №2:

Оригинальный плакат здесь:

Проблема была вызвана тем фактом, что pip установит пакет на уровне my_package , поэтому полагаясь на то, что импорт будет настроен либо как .helpers , либо my_package.helpers как , тогда как запуск скрипта my_package.py не устанавливает пакет, и поэтому импорт должен быть написан по-другому.

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