Ответ 1
Хорошо, поэтому, после некоторого усилия, мне наконец-то удалось получить простой "привет мир" пример для setuptools. Документация на Python обычно потрясающая, но я хочу, чтобы документация была лучше в этом, в частности.
Я собираюсь написать довольно подробное руководство о том, как я это достиг, и я не буду предполагать, что у читателя по этому вопросу нет предварительной информации. Надеюсь, это пригодится другим...
Чтобы настроить этот пример, мы создадим пакет (фактически два из них, один для файлов данных). Это структура каталогов, в которой мы закончим:
test-setuptools/
|-- helloworld/
|-- --- hello.py
|-- --- images/
|-- --- --- hello.gif
|-- --- --- __init__.py
|-- --- __init__.py
|-- MANIFEST.in
|-- README.txt
|-- setup.py
Вот шаги:
-
Создайте пакет
helloworld
.
1.1 Создайте папкуhelloworld/
, как показано в структуре каталогов выше.1.2 Добавьте пустой файл с именем
__init__.py
в папкуhelloworld/
.
Если вы его не добавите, пакет не будет распознан (запуститеtouch __init__.py
, чтобы создать файл на машинах linux/mac). Если вы хотите, чтобы какой-либо код выполнялся каждый раз при импорте пакета, включите его в файл__init__.py
.1.3 Создайте файл
hello.py
script, чтобы продемонстрировать функциональность пакета.
Вот код для hello.py
:
import os
"""
Open additional data files using the absolute path,
otherwise it doesn't always find the file.
"""
# The absolute path of the directoy for this file:
_ROOT = os.path.abspath(os.path.dirname(__file__))
class Hello(object):
def say_hello(self):
return "Hello, World!"
def open_image(self):
print("Reading image.gif contents:")
# Get the absolute path of the image relative path:
absolute_image_path = os.path.join(_ROOT, 'images/hello.gif')
with open(absolute_image_path, "r") as f:
for line in f:
print(line)
-
1.4 Создайте папку
images/
внутри папкиhelloworld/
.
Сделайте еще один пустой файл__init__.py
, потому что эта папка также будет пакетом.1.5 Создайте файл
hello.gif
внутри папкиimages/
.
Этот файл не будет фактическим gif файлом. Вместо этого добавьте простой текст, чтобы продемонстрировать, что файлы без script могут быть добавлены и прочитаны.
Я добавил следующий код в hello.gif
:
This should be the data inside hello.gif...
...but this is just to demonstrate setuptools,
so it a dummy gif containing plain text
-
1.6 Проверьте свой пакет
Запуститеpython
из папкиtest-setuptools
, которая откроет интерпретатор python.
Введитеimport helloworld.hello
, чтобы импортироватьhello.py
script в пакетhelloworld
. Импорт должен быть успешным, указывая, что вы успешно создали пакет. Убедитесь, что пакет в папкеimages/
также работает, набравimport helloworld.images
Попробуйте создать экземпляр объекта, который мы написали вhello.py
. Введите следующие команды, чтобы убедиться, что все работает так, как ожидалось:hey = helloworld.hello.Hello()
hey.say_hello()
hey.open_image()
-
Создайте файл
setup.py
и остальные файлы.
2.1 Создайте простой файлREADME.txt
. Мой имеет только текст:Hello, World! Readme
внутри.2.2 Создайте файл
MANIFEST.in
со следующим содержимым:include helloworld/images/hello.gif
.
Это очень важно важно, потому что он сообщает setuptools включать дополнительные данные в исходный дистрибутив (который мы сгенерируем на более позднем этапе). Без этого вы не сможете установить дополнительные, не.py
данные в свой пакет. Подробнее см. .2.3 Создайте файл
setup.py
(см. код ниже).
Наиболее важными атрибутами являютсяpackages
,include_package_data
иpackage_data
.
.
Атрибутpackages
содержит список пакетов, которые вы хотите включить для setuptools. Мы хотим включить пакетhelloworld
и пакетhelloworld.images
, содержащий наши дополнительные данныеhello.gif
.
Вы можете заставить setuptools автоматически найти их, добавивfrom setuptools import find_packages
импорт и запуск импортированной функцииfind_packages()
. Запустите интерпретатор из папкиtest-setuptools
и проверьте эту команду, чтобы узнать, какие пакеты найдены.
.
Атрибутpackage_data
сообщает setuptools включать дополнительные данные. Это эта команда, пакетhelloworld.images
и файлMANIFEST.in
, которые позволяют устанавливать дополнительные данные.
Пара ключей/значений'helloworld.images' : ['hello.gif']
сообщает setuptools включатьhello.gif
в пакетhelloworld.images
, если он существует. Вы также можете сказать'' : ['*.gif']
, чтобы включить любой .gif файл в любой из включенных пакетов.
Для этого необходим атрибутinclude_package_data
, установленный наTrue
.
Вы можете включить дополнительные метаданные для пакета, как у меня (я думаю, нуженauthor
). Это хорошая идея добавить классификаторы. Дополнительную информацию можно найти здесь.
Вот весь код setup.py
:
from setuptools import setup
setup(
name='helloworld',
version='0.1',
license='BSD',
author='gyeh',
author_email='[email protected]',
url='http://www.hello.com',
long_description="README.txt",
packages=['helloworld', 'helloworld.images'],
include_package_data=True,
package_data={'helloworld.images' : ['hello.gif']},
description="Hello World testing setuptools",
)
.
3. Установите и протестируйте свой пакет с помощью setuptools.
3.1 Create the source distribution
Запустите python setup.py sdist
из папки test-setuptools/
, чтобы создать исходный дистрибутив.
Это создаст папку dist/
, содержащую ваш пакет, и папку helloworld.egg-info/
, содержащую метаданные, такие как SOURCE.txt
.
Проверьте SOURCE.txt
, чтобы увидеть, включен ли в него файл изображения hello.gif
.
Откройте файл .tar.gz
в папке dist/
. Вы должны увидеть все файлы, описанные в ранее созданной структуре каталогов, включая hello.gif
и hello.py
.
3.2 Install the distribution
Установите файл распространения .tar.gz, запустив pip install --user helloworld-0.1.tar.gz
из папки dist/
.
Убедитесь, что пакет был успешно установлен, запустив pip list
. Пакет helloworld
должен быть там.
Что это! теперь вы сможете проверить свой пакет под любой папкой. Откройте интерпретатор в любой папке, кроме test-setuptools
, и попробуйте импортировать пакет с помощью import helloworld.hello
. Он должен работать. Затем попробуйте команды для создания экземпляра объекта и снова откройте файл изображения с помощью команды hey.open_image()
. Он все равно должен работать!
Вы можете точно определить, какие файлы были установлены в pip, и где они находятся, путем удаления пакета. Мой выглядел так:
[[email protected] package]$ pip uninstall helloworld
Uninstalling helloworld:
/home/gyeh/.local/lib/python3.3/site-packages/helloworld-0.1-py3.3.egg-info
/home/gyeh/.local/lib/python3.3/site-packages/helloworld/__init__.py
/home/gyeh/.local/lib/python3.3/site-packages/helloworld/__pycache__/__init__.cpython-33.pyc
/home/gyeh/.local/lib/python3.3/site-packages/helloworld/__pycache__/hello.cpython-33.pyc
/home/gyeh/.local/lib/python3.3/site-packages/helloworld/hello.py
/home/gyeh/.local/lib/python3.3/site-packages/helloworld/images/__init__.py
/home/gyeh/.local/lib/python3.3/site-packages/helloworld/images/__pycache__/__init__.cpython-33.pyc
/home/gyeh/.local/lib/python3.3/site-packages/helloworld/images/hello.gif
Proceed (y/n)? y
Successfully uninstalled helloworld
Как вы можете видеть, он успешно установил дополнительный файл данных hello.gif
, и поскольку мы преобразовали относительный путь к абсолютному пути в hello.py
, он может отлично прочитать файл.
Затем вы можете поделиться этим пакетом на PyPI для остального мира! Инструкции по загрузке в PyPI довольно просты и здесь можно найти здесь и здесь.
Как только он будет доступен в PyPI, люди смогут выполнить поиск вашего пакета с помощью pip search
. Или, наоборот, при запуске pip install --user [package-name]
будет указывать pip для поиска в онлайн-директории PyPI для этого имени пакета. Если он существует, он установит его.
Вы можете запустить эту команду для любого пакета python, который в PyPI для простой установки, чтобы вы не обманывали файлы сборки.
Надеюсь, это избавит людей от кучи головных болей.