Я опубликовал пакет PyPI, для которого требуются некоторые дополнительные пакеты Apt, поэтому в моем репозитории Github есть setup.sh
, который я хочу выполнить вместе с процессом установки pip install mypackage
(т. е. всякий раз, когда пользователь запускает pip install mypackage
, он должен запускать сценарий оболочки во время процесс установки.)
Я сделал setup.py
, чтобы использовать параметр cmdclass вот так
from setuptools import setup, find_packages
from setuptools.command.install import install
import subprocess
import codecs
import os
class CustomInstall(install):
def run(self):
subprocess.check_call("bash setup.sh", shell=True)
install.run(self)
with open('requirements.txt') as f:
requirements = f.read().splitlines()
setup(
...
cmdclass = {'install': CustomInstall}, install_requires=requirements,
...
)
Когда я обычно собираю его с помощью python setup.py sdist bdist_wheel
, класс Custominstall
работает нормально, но во время установки pip он игнорирует класс Custominstall
.
Наконец я нашел эту ветку stackoverflow, из которой я узнал, что мне нужно только запустить python setup.py sdist
, что я и сделал, и получил файл tar.gz в папке dist
, но когда я перехожу к установке этого файла tar.gz с помощью pip install, я получаю
with open('requirements.txt') as f:
^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'requirements.txt'
Что я делаю не так? Путь неверный? Файл требований находится в родительской папке моего репозитория (а не внутри какой-либо другой папки).
🤔 А знаете ли вы, что...
В Python есть среды разработки, такие как Jupyter Notebook, которые упрощают работу с данными и исследованиями.
Непосредственная проблема заключается в том, что процесс pip
запускается в любом каталоге, в котором находится вызывающий пользователь. Возможно, см. Также Что такое текущий рабочий каталог?
Решение этой проблемы: Как мне получить путь и имя файла Python, который выполняется в данный момент? -- по сути, проверьте __file__
и извлеките из него каталог, к которому вы хотите получить доступ.
Однако предпосылка вашего вопроса кажется глубоко ошибочной. Вам следует объявить зависимости от тех пакетов Python, от которых вы зависите, и позволить pip
взять их оттуда; или же создайте пакет Debian, а затем объявите все свои зависимости в терминах других пакетов Debian. (Конечно, вы можете сделать и то, и другое. Конечно, в последнем случае вам, вероятно, следует сделать и первое, чтобы ваш пакет можно было установить на платформах, отличных от Debian.)
Вы не сообщили нам, от каких пакетов будет зависеть ваш, поэтому мы можем сформулировать это только в самых общих чертах. Допустим, ваша посылка зависит от requests
и beautifulsoup4
. Тогда ваш setup.py
должен объявить эти зависимости:
setup(
...
install_requires=["requests", "beautifulsoup4"],
...
)
Для удобства вы также можете объявить их в requirements.txt
, но этот файл не играет формальной роли в упаковке Python. Ваши зависимости должны быть объявлены в setup.py
(или для современных пакетов определенно предпочтительнее pyproject.toml
или setup.cfg
).
Если некоторые из этих зависимостей можно выполнить через менеджер пакетов ОС, предоставление другого механизма установки для удобства не является обязательным, но является приятным дополнением. Ваш пакетный скрипт не должен от этого зависеть (а возможно и наоборот).
#!/bin/sh
apt-get install -y python3-requests python3-bs4
(Возможно, обратите внимание также на то, что пакеты Debian обычно имеют другие имена, чем соответствующие пакеты Python. Это неприятно, но в принципе неизбежно.)
Причина, по которой это происходит, заключается в том, что ваш setup.py
зависит от requirements.txt
, но вы не упаковываете requirements.txt
в свой дистрибутив. Если вы откроете .tar.gz
, вы не найдете свой requirements.txt
файл. Чтобы это исправить, создайте файл MANIFEST.in
с содержимым:
include requirements.txt
И добавьте include_package_data=True
к своему setup
звонку.
Вам нужно будет добавить любые другие файлы, не относящиеся к Python, которые вы хотите включить в свой дистрибутив .tar.gz
, например, ваш скрипт setup.sh
.
Когда вы создадите свой исходный дистрибутив с этими изменениями, вы увидите, что requirements.txt
теперь включен в содержимое вашего дистрибутива сборки.
Альтернативно, вы также можете использовать для этого ключевое слово package_data
в setup
(или [options.package_data]
в setup.cfg
). См.: эту ссылку для более подробного объяснения.
Однако, вообще говоря, запускать сценарии оболочки или устанавливать системные пакеты как часть вашего setup.py
. Это усложнит использование вашего пакета, а не упростит его.
Если ваш пакет зависит от зависимостей Python, используйте вместо него install_requires
.