Я пытаюсь сделать мой проект Python доступным для импорта людьми, которые устанавливают его с помощью pip
. Хотя он содержит __init__.py
и работает как пакет локально, похоже, я неправильно понимаю, как работает setuptools.
Я запускаю следующие три команды, чтобы загрузить пакет.
python3 setup.py sdist bdist_wheel
python3 -m pip install --upgrade twine
python3 -m twine upload dist/*
Потом на другой машине запускаю pip3 install smux.py
. В результате я могу получить доступ к smux.py
как к команде, но при попытке импорта я получаю сообщение об ошибке импорта.
python3
Python 3.8.5 (default, Jul 28 2020, 12:59:40)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import smux
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'smux'
После выполнения приведенных выше команд setup.py
я проверил smux.py.egg-info/SOURCES.txt
в текущем каталоге и обнаружил, что он содержит следующее:
README.md
setup.py
smux.py
smux.py.egg-info/PKG-INFO
smux.py.egg-info/SOURCES.txt
smux.py.egg-info/dependency_links.txt
smux.py.egg-info/top_level.txt
Файл __init__.py
отсутствует.
Как мне добавить этот файл в пакет или изменить вызов установки, чтобы сделать smux
импортируемым?
🤔 А знаете ли вы, что...
Python подходит для начинающих программистов благодаря своей простоте и читаемости кода.
Ваш звонок setup
выглядит так:
setup(
name = "smux.py",
version='0.1.1',
scripts=['smux.py'],
author = "Henry Qin",
author_email = "[email protected]",
description = "Simple tmux launcher that will take less than 2 minutes to learn and should work across all versions of tmux",
long_description=long_description,
platforms=["All platforms that tmux runs on."],
license = "MIT",
url = "https://github.com/hq6/smux"
)
С помощью аргумента scripts
вы сообщаете setuptools, что smux.py
— это скрипт, а не модуль. Соответственно, он устанавливается как скрипт, а не как модуль.
Ваш код не нуждается в __init__.py
и не должен его иметь. Наличие __init__.py
не поможет. Вам нужно указать setuptools установить ваш файл как модуль, а не скрипт, и отдельно зарегистрировать точку входа с записью console_scripts в аргументе entry_points
:
setup(
...
# no scripts= line
py_modules=['smux'],
entry_points = {
'console_scripts': ['smux=smux:main']
}
)
Затем, когда ваш код будет установлен, smux
можно будет импортировать, и в командной строке будет доступен скрипт smux
, который вызывает smux.main
.
Другой ответ более кошерный и современный, и я бы использовал его и назвал сценарий smux
, если бы у меня не было устаревших сценариев, зависящих от имени smux.py
. К сожалению, другие завернули smux.py
, и было бы нехорошо сломать их скрипты.
Вот что я сделал, чтобы избежать проблемы циклической зависимости, возникающей из-за того, что имя устаревшего скрипта оканчивается на .py
и конфликтует с именем модуля.
Я закончил тем, что изменил вызов setup
, чтобы иметь оба следующих.
py_modules=['smux'],
scripts=['smux.py']
Мои эксперименты показывают, что это дает желаемый эффект: делает модуль импортируемым при сохранении рабочего скрипта под именем smux.py
.