#python-3.x #build #package #pypi #modulenotfounderror
#python-3.x #сборка #пакет #pypi #ошибка modulenotfounderror
Вопрос:
Я пытаюсь создать свой первый пакет python и опубликовать его в PyPI. Моя цель — предоставить определенную функцию через CLI, чтобы конечный пользователь мог установить ее через pip, например pip3 install my-package
, и использовать ее непосредственно из терминала my-package -fa first_argument -sa second_argument
.
Допустим, вызывается мой пакет fp-test-package
. Я сделал макет структуры папок моего проекта, который вы можете найти здесь https://github.com/fabiopipitone/fp-test-package .
В макете я также вставил в качестве требований один из пакетов, необходимых в реальном проекте (tqdm), и сохранил точно такое же соглашение (дефис во внешней папке и репозитории github, подчеркивания для внутренних пакетов, одинаковая позиция и импорт для помощников и утилит и так далее). Таким образом, если он работает на макете, он должен работать и на реальном проекте.
Вот структура каталога проекта
fp-test-package
├── fp_test_package
│ ├── __init__.py
│ ├── fp_test_package.py
│ ├── helpers
│ │ ├── arguments_checkers.py
│ │ ├── csv_handlers.py
│ │ └── utility_functions.py
│ └── utils
│ ├── __init__.py
│ ├── CustomLogger.py
│ └── TqdmLoggingHandler.py
├── LICENSE
├── README.rst
├── requirements.txt
├── setup.py
├── docs
└── tests
Вот что такое setup.py
from setuptools import setup, find_packages
with open("README.rst", "r") as fh:
long_description = fh.read()
setup(
name ='fp-test-package',
version ='0.0.1',
description='Simple test building a CLI tool package',
long_description=long_description,
long_description_content_type='text/x-rst',
license ='GPLv2',
packages = find_packages(),
entry_points ={
'console_scripts': [
'fp_test_package = fp_test_package.py:main'
]
},
classifiers =(
"Programming Language :: Python :: 3",
"License :: OSI Approved :: GNU General Public License v2",
"Operating System :: Linux",
),
keywords ='test packaging fabiopipitone',
install_requires = ['tqdm>=4.49.0'],
zip_safe = False
)
Я попробовал следовать нескольким инструкциям о том, как создавать и публиковать пакет CLI python, затем я попробовал sudo python3 setup.py install
из fp-test-package
каталога (тот же уровень setup.py ). Кажется, он устанавливает пакет (я могу найти запись fp-test-package==0.0.1
в pip3 freeze
), но если я попробую fp-test-package
в терминале, он вернется fp-test-package: command not found
, если я попробую fp_test_package
, он вернется:
Traceback (most recent call last):
File "/usr/local/bin/fp_test_package", line 11, in <module>
load_entry_point('fp-test-package==0.0.1', 'console_scripts', 'fp_test_package')()
File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 490, in load_entry_point
return get_distribution(dist).load_entry_point(group, name)
File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 2854, in load_entry_point
return ep.load()
File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 2445, in load
return self.resolve()
File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 2451, in resolve
module = __import__(self.module_name, fromlist=['__name__'], level=0)
ModuleNotFoundError: No module named 'fp_test_package.py'
Затем я пошел с sudo pip3 uninstall fp_test_package
, который успешно удалил пакет. Я удалил ранее созданные build
dist
fp_test_package.egg-info
каталоги и и попробовал pip3 install -e .
(снова изнутри fp-test-package
). Он создал fp_test_package.egg-info
каталог, но опять же, запустив fp_test_package
консоль, он возвращает
Traceback (most recent call last):
File "/usr/local/bin/fp_test_package", line 11, in <module>
load_entry_point('fp-test-package==0.0.1', 'console_scripts', 'fp_test_package')()
File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 490, in load_entry_point
return get_distribution(dist).load_entry_point(group, name)
File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 2854, in load_entry_point
return ep.load()
File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 2445, in load
return self.resolve()
File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 2451, in resolve
module = __import__(self.module_name, fromlist=['__name__'], level=0)
ModuleNotFoundError: No module named 'fp_test_package.py'
Итак, чего мне не хватает? Я хотел бы просто упаковать и установить его, чтобы при вводе пользователем fp-test-package
or fp_test_package
он возвращал сообщение об ошибке о требуемом --export_path
аргументе (означает, что скрипт запущен правильно), например, когда я вызываю его с консоли:
$ python3 fp_test_package/fp_test_package.py
usage: fp_test_package.py [-h] -ep EXPORT_PATH [-sa SECOND_ARGUMENT] [-ta THIRD_ARGUMENT]
fp_test_package.py: error: the following arguments are required: -ep/--export_path
Как я могу это сделать?
РЕДАКТИРОВАТЬ: я заметил, что @Dustin затем указал на setup.py . На самом деле, мой коллега создал фиктивный репозиторий, изменив console_scripts
часть. Теперь на моей машине коллеги все работает так, как ожидалось. На моем, после извлечения репозитория и повторного запуска python3 setup.py install
, при вызове fp_test_package
из консоли он возвращает следующее:
Traceback (most recent call last):
File "/usr/local/bin/fp_test_package", line 11, in <module>
load_entry_point('fp-test-package==0.0.1', 'console_scripts', 'fp_test_package')()
File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 490, in load_entry_point
return get_distribution(dist).load_entry_point(group, name)
File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 2854, in load_entry_point
return ep.load()
File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 2445, in load
return self.resolve()
File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 2451, in resolve
module = __import__(self.module_name, fromlist=['__name__'], level=0)
File "/usr/local/bin/fp_test_package.py", line 4, in <module>
__import__('pkg_resources').run_script('fp-test-package==0.0.1', 'fp_test_package.py')
File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 667, in run_script
self.require(requires)[0].run_script(script_name, ns)
File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 1452, in run_script
raise ResolutionError(
pkg_resources.ResolutionError: Script 'scripts/fp_test_package.py' not found in metadata at '/usr/local/lib/python3.8/dist-packages/fp_test_package-0.0.1-py3.8.egg/EGG-INFO'
Есть идеи?
Ответ №1:
У вас setup.py
есть:
entry_points ={
'console_scripts': [
'fp_test_package = fp_test_package.py:main'
]
},
Это эквивалентно следующему импорту:
from fp_test_package.py import main as fp_test_package
Проблема в том, что у вас нет fp_test_package.py
модуля, у вас есть fp_test_package
модуль (каталог с __init__.py
файлом), который содержит fp_test_package
подмодуль (имена модулей не включают расширение).
Предполагая, что ваш fp_test_package.py
файл определяет main
функцию, вы можете изменить это на:
entry_points ={
'console_scripts': [
'fp_test_package = fp_test_package.fp_test_package:main'
]
},
Или вы могли бы переместить свою main
функцию в fp_test_package/__init__.py
, чтобы она могла быть:
entry_points ={
'console_scripts': [
'fp_test_package = fp_test_package:main'
]
},
Комментарии:
1. Я заметил, на что вы указали, и мой коллега выбрал репозиторий git. После слияния вы можете заметить изменения в
setup.py
том же решении, которое вы опубликовали. Что забавно, так это то, что теперь все работает на моей машине коллеги, но после того, как я вытащил новую версию и повторно запустил установку сpython3 setup.py install
помощью , при попытке использовать пакетfp_test_package
с помощью консоли он возвращает: « … pkg_resources. Ошибка разрешения: сценарий ‘scripts/fp_test_package.py ‘ не найдено в метаданных по адресу ‘/usr/local/lib/python3.8/dist-packages/fp_test_package-0.0.1-py3.8.egg/EGG-INFO’ «2. Вам необходимо полностью удалить пакет и переустановить его, желательно с
pip install .
помощью instead .3. Что вы подразумеваете под его полной отменой? Я пошел с
sudo pip3 uninstall fp_test_package
, а затемsudo rm -rf fp_test_package.egg-info dist build
удалил созданные каталоги. Затем я попробовал обаsudo python3 setup.py install
иpip3 install -e .
(сначала один, затем удалите все и попробуйте другой), и оба возвращают одну и ту же ошибку. Я даже пробовал с venv. Та же ошибка. После установки, запускаpip3 list
, только строка моего пакета (fp-test-package 0.0.1
) имеетLocation
значение столбца (на компьютере моего коллеги оно пустое). Это что-нибудь значит?4. Все
/usr/local/lib/python3.8/dist-packages/fp_test_package-0.0.1-py3.8.egg
еще существует после его удаления?5. Это не так. После
pip3 uninstall fp_test_package
и всеrm -rf
, если я запускаюсьfind . -name fp_test*
как пользователь sudo из/
, я получаю только./home/fabio/Desktop/test_python_package/fp-test-package/fp_test_package
и./home/fabio/Desktop/test_python_package/fp-test-package/fp_test_package/fp_test_package.py
, тогда единственными ссылками наfp_test*
являются ссылки наfp-test-package
папку. Теперь, если я запущуpip3 install -e .
столбец местоположенияfp_test_package
строки вpip3 list
шоу/home/fabio/Desktop/test_python_package/fp-test-package
.
Ответ №2:
Хорошо, в конце концов я нашел проблему в моем конкретном случае. Что вызвало эту загадочную ошибку при установке с python3 setup.py install
pkg_resources.ResolutionError: Script 'scripts/fp_test_package.py' not found in metadata at '/usr/local/lib/python3.8/dist-packages/fp_test_package-0.0.1-py3.8.egg/EGG-INFO'
или эквивалентная ошибка при установке с pip3 install .
pkg_resources.ResolutionError: Script 'scripts/fp_test_package.py' not found in metadata at '/home/fabio/Desktop/test_python_package/fp-test-package/fp_test_package-0.0.1-py3.8.egg/EGG-INFO'
было отсутствие в переменной $PATH требуемого пути для правильного запуска скрипта.
Подводя итог, то, что я сделал, было:
- редактирование
setup.py
файла в соответствии с предложениями Дастина оconsole_scripts
- сборка и установка запущенного пакета
pip3 install .
(илиpip3 install -e .
, если вы хотите, редактируемой версии) изfp-test-package
папки. - проверка того, с помощью чего был создан двоичный файл скрипта
which fp_test_package
(в моем случае/home/fabio/.local/bin/fp_test_package
) - добавив это
path
в переменную $PATH env (в моем.bashrc
— и.zshrc
с тех пор, как я используюzsh
— я добавил строкуexport PATH="$HOME/.local/bin:$PATH"
)
Теперь все работает так, как ожидалось. Я не буду удалять правильную версию репозитория, поэтому, если кто-то хочет использовать рабочий скелет для запуска проекта, его можно найти там.