Я экспериментирую с помещением кода Python в стандартную структуру каталогов, используемую для развертывания с setup.py
и, возможно, PyPI. для библиотеки Python под названием MyLib было бы что-то вроде этого:Вызов сценария в стандартной структуре каталога проекта (Python path for bin subdirectory)
mylibsrc/
README.rst
setup.py
bin/
some_script.py
mylib/
__init.py__
foo.py
Там часто также подкаталог test/
, но я не пробовал писать юнит-тесты еще. Рекомендация о наличии сценариев в подкаталоге bin/
может быть найдена в official Python packaging documentation.
Конечно, скрипты начинаются с кодом, который выглядит следующим образом:
#!/usr/bin/env python
from mylib.foo import something
something("bar")
Это хорошо работает, когда он в конце концов приходит к развертыванию сценария (например, для devpi), а затем установить его с пипом. Но если я запускаю сценарий непосредственно из исходного каталога, как я бы при разработке новых изменений в библиотеке/сценарий, я получаю эту ошибку:
ImportError: No module named 'mylib'
Это верно, даже если текущий рабочий каталог является корневым mylibsrc/
и я запустил скрипт, набрав ./bin/some_script.py
. Это связано с тем, что Python начинает поиск пакетов в каталоге запускаемого сценария (т. Е. От bin/
), а не в текущем рабочем каталоге.
Что такое хороший способ, позволяющий легко запускать скрипты при разработке пакетов?
Вот relevant other question (особенно комментарии к первому ответу).
Решения для этого, что я нашел до сих пор делятся на три категории, но ни один из них не являются идеальными:
- вручную подправить свой путь поиска модулей Python, как-то перед запуском скриптов.
- Вы можете добавить
mylibsrc
в мою переменную окруженияPYTHONPATH
. Это, по-видимому, самое официальное решение (Pythonic?), Но означает, что каждый раз, когда я просматриваю проект, я должен помнить о том, чтобы вручную изменить свою среду, прежде чем я смогу запустить в ней какой-либо код. - Добавить
.
в начало моей переменнойPYTHONPATH
. Насколько я понимаю, это может иметь некоторые проблемы с безопасностью. На самом деле это был бы мой любимый трюк, если бы я был единственным человеком, который использовал бы мой код, но я не, и я не хочу просить других об этом. - Рассматривая ответы в Интернете, для файлов в каталоге
test/
, я видел рекомендации, что все они (косвенно) содержат строку кодаsys.path.insert(0, os.path.abspath('..'))
(например, в structuring your project). Тьфу! Это похоже на переносимый взлом для файлов, которые предназначены только для тестирования, но не для тех, которые будут установлены вместе с пакетом. - Редактировать: С тех пор я нашел альтернативу, которая оказалась в этой категории: путем запуска скриптов с помощью скрипта Python
-m
путь поиска начинается в рабочем каталоге, а не в каталогеbin/
. См. Мой ответ ниже для более подробной информации.
- Вы можете добавить
- Установите пакет в виртуальную среду перед его использованием, используя setup.py (либо запуская его напрямую, либо используя pip).
- Это кажется излишним, если я просто тестирую изменение, которое я не уверен, даже синтаксически корректно. Некоторые из проектов, над которыми я работаю, даже не предназначены для установки в виде пакетов, но я хочу использовать одну и ту же структуру каталогов для всего, и это будет означать запись setup.py, чтобы я мог их протестировать!
- Редактировать: Два интересных варианта этого обсуждаются в ответах ниже: команда
setup.py develop
в ответе logc иpip install -e
в моем. Они избегают необходимости «устанавливать» для каждого небольшого редактирования, но вам все равно нужно создатьsetup.py
для пакетов, которые вы никогда не собираетесь полностью устанавливать, и не очень хорошо работает с PyCharm (у которого есть запись меню для запускаdevelop
но нет простого способа запуска скриптов, которые он копирует в виртуальную среду).
- Переместите сценарии в корневой каталог проекта (то есть в
mylibsrc/
вместоmylibsrc/bin/
).- Yuck! Это последнее средство
, но, к сожалению, это похоже на единственный возможный вариант на данный момент.
- Yuck! Это последнее средство
Спасибо за подробный ответ. Материал о «entry_points» интересен, но не хватает всего: я не хочу устанавливать пакет, чтобы попробовать все крошечные экспериментальные изменения (на самом деле это делает это хуже!). Но вы упомянули мимоходом самородок, который является реальным решением: команда 'setup.py develop'. Это будет работать как с «entry_points», так и с обычными скриптами. Жаль, что он требует, чтобы вы создавали 'setup.py' даже для пакетов, которые вы никогда не намерены правильно устанавливать, и нелегко получить доступ из среды IDE, такой как PyCharm. –