Перейти к содержимому

Setup py что это

  • автор:

Обьясните пожалуйста работу setup.py и distutils?

Если я правильно понял ,то distutils это модуль который позволяет вам собирать свои собственные модули,для того чтобы в дальнейшем люди могли установить их обычный строкой «pip install . «, а setup.py это python файл ,который как раз и производит эту простую Установку?Правильно ли я все понял или нет,обьясните пожалуйста .

  • Вопрос задан более трёх лет назад
  • 1659 просмотров

2 комментария

Простой 2 комментария

longclaps

Правильно, но недостаточно.
Оно и к лучшему — не стоит засирать вселенную ненужными модулями. Поверь.

Создание python-пакетов (aka setup scripts)

Одна из действительно полезных вещей в python — это система скриптов установки. Любой, серьезно увлекающийся python-программированием разработчик рано или поздно сталкивается с ней. Но из-за гибкости инструментария скриптов установки, их документация весьма раздута. На текущий момент имеется набор утилит (setuptools, distutils, distribute) выполняющих одинаковые задачи.

В данной статье я на конкретных примерах покажу как создать и настроить простой python-пакет.

Наш проект будет иметь следующую функциональность:

  • Метод возвращающий строку: «Hello World!»;
  • Команда helloworld печатающая эту строку в стандартный вывод.

Создаем структуру проекта

Для начала создадим директорию для пакета. Ее минимальный набор файлов состоит из: файла дистрибьюции ( setup.py ) описывающего метаданные и python кода проекта (в нашем случае модуля helloworld).

Также, xорошим тоном считается создание в корне директории файла с описанием проекта: README.txt .

Получаем следующую структуру:

helloworld-project ├── helloworld │ ├── __init__.py │ └── core.py ├── setup.py └── README.txt

Наша корневая директория helloworld-project будет содержать мета-данные пакета и вспомогательные файлы (тесты, лицензию, документацию и т.д.), а поддиректория helloworld непосредственно сам модуль helloworld .

Теперь отредактируем файл: helloworld/core.py и добавим логику нашего приложения (получение и вывод строки «Hello World!»):

def get_message(): return "Hello World!" def print_message(): print get_message() 

Редактируем мета-информацию (setup.py)

Заполним файл описания README.rst :

Description =========== An example Hello World project.

Теперь отредактируем файл setup.py :

from setuptools import setup, find_packages from os.path import join, dirname setup( name='helloworld', version='1.0', packages=find_packages(), long_description=open(join(dirname(__file__), 'README.txt')).read(), ) 

Убедитесь, что в вашей системе доступны setuptools, в противном случае установите python-пакет distribute

Этих операций достаточно, чтобы собрать пакет дистрибьюции. Выполните команду сборки:

$ python setup.py sdist

В случае успеха вы получите файл: dist/helloworld-1.0.tar.gz . Это полноценный, архивированный python-пакет и вы можете распространять его среди прочих разработчиков.

Виртуальное окружение

Virtualenv — пакет применяемый для создания изолированного python-окружения. Используем его для тестирования нашего проекта.

Создадим окружение env:

$ virtualenv env

Команда создаст директорию env внутри нашего проекта и установит туда python, pip и distribute. Произведем в него установку нашего проекта.

$ ./env/bin/python setup.py install running install running bdist_egg running egg_info [. ] Processing dependencies for helloworld==1.0 Finished processing dependencies for helloworld==1.0

И протестируем его работоспособность:

$ ./env/bin/python >>> import helloworld.core as hw >>> hw.get_message() 'Hello World!' >>> hw.print_message() Hello World!

Все работает. Осталось добавить поддержку команды helloworld в консоли.

Создание команд

Для создания команды helloworld изменим файл setup.py :

setup( . entry_points= 'console_scripts': ['helloworld = helloworld.core:print_message'] > ) 

В параметре entry_points мы задаем словарь с «точками вызова» нашего приложения. Ключ console_scripts задает список создаваемых исполняемых скриптов (в Windows это будут exe-файлы). В данном случае мы указали создание исполняемого скрипта helloworld при вызове которого будет запускаться метод print_message из модуля helloworld.core.

Переустановим модуль в наше окружение и проверим работу созданного скрипта (для этого прийдется активировать наше окружение):

$ ./env/bin/python setup.py install $ source ./env/bin/activate (env) $ helloworld Hello World! (env) 

Похоже все работает.

Работа с версиями

Номер версии важная часть любого проекта. От него зависит обновление пакетов и разрешение зависимостей. В примере выше мы указали номер версии 1.0 в файле setup.py . Более правильное решение перенести его в файл helloworld/__init__.py чтобы сделать доступным в python-коде. По существующим соглашения для хранения номера версии в модуле, используется переменная __version__.

__version__ = '1.0' 

Изменим файл setup.py , чтобы нам не приходилось редактировать номер версии в двух местах:

. import helloworld setup( name='helloworld', version=helloworld.__version__, . 

Существует множество систем наименования версий в python обычно рекомендуется использовать PEP386. Можно представить, что обозначение версии состоит из номера мажорного, минорного релизов (номера багфикса при необходимости), разделенных точками. В последней части версии разрешается использовать буквы латинского алфавита. Примеры из официальной документации:

0.4 0.4.0 (these two are equivalent) 0.4.1 0.5a1 0.5b3 0.5 0.9.6 1.0 1.0.4a3 1.0.4b1 1.0.4

Управление зависимостями

Добавим функциональности нашему проекту. Создадим команду serve которая будет запускать вебсервер отдающий страницу со строкой «Hello world!» генерируемой нашим модулем. Для этого воспользуемся пакетом Flask.

Добавляем файл helloworld/web.py :

from flask import Flask, render_template from helloworld.core import get_message app = Flask(__name__) @app.route("/") def hello(): return render_template('index.html', message=get_message()) def run_server(): app.run() 

И файл helloworld/templates/index.html :

 body>>body> 

И опишем команду serve в файле setup.py :

. entry_points= 'console_scripts': [ 'helloworld = helloworld.core:print_message', 'serve = helloworld.web:run_server', ] >, . 

Теперь в нашем проекте появилась зависимость от пакета Flask. Без его установки наше приложение не будет правильно работать. За описание зависимостей в файле setup.py отвечает параметр install_requires:

. install_requires=[ 'Flask==0.8' ] 

Проверим установку зависимостей обновив наш пакет и работу команды serve:

$ ./env/bin/python setup.py develop . Processing dependencies for helloworld==0.1 Searching for Flask==0.8 . $ serve * Running on http://127.0.0.1:5000/

Открыв браузер по адресу http://127.0.0.1:5000 вы должны увидеть нашу страницу.

Управление файлами проекта (MANIFEST.in)

На текущий момент при сборке нашего пакета distutils включает в него только python-файлы. Необходимо включить в него файл helloworld/templates/index.html без которого проект работать не будет.

Чтобы сделать это мы должны сообщить distutils какие еще файлы надо включать в наш проект. Один из способов — это создание файла MANIFEST.in :

recursive-include helloworld/templates *.html

Данная команда указывает distutils на включение в проект всех html файлов в директории helloworld/templates .

Также придется обновить setup.py :

. setup( . include_package_data=True, . ) 

Теперь шаблоны будут включены в наш проект.

Создание и запуск тестов

Хорошей практикой считается создание тестов для вашего проекта. Добавим простейшую реализацию, файл tests.py :

from unittest import TestCase from helloworld.core import get_message class HelloworldTestCase(TestCase): def test_helloworld(self): self.assertEqual(get_message(), 'Hello World!') 

И обновим setup.py :

. setup( . test_suite='tests', . ) 

Теперь мы можем произвести предварительное тестирование нашего проекта:

$ python setup.py test running test running egg_info writing requirements to helloworld.egg-info/requires.txt writing helloworld.egg-info/PKG-INFO writing top-level names to helloworld.egg-info/top_level.txt writing dependency_links to helloworld.egg-info/dependency_links.txt writing entry points to helloworld.egg-info/entry_points.txt reading manifest file 'helloworld.egg-info/SOURCES.txt' reading manifest template 'MANIFEST.in' writing manifest file 'helloworld.egg-info/SOURCES.txt' running build_ext test_helloworld (tests.HelloworldTestCase) . ok ---------------------------------------------------------------------- Ran 1 test in 0.000s OK

Обратите внимание, что для запуска тестов даже не нужно создание виртуального окружения. Необходимые зависимости будут скачаны в директорию проекта в виде egg пакетов.

Публикация пакета на pypi.python.org

Прежде чем вы сможете опубликовать свой проект вам необходимо зарегистрироваться на PyPi. Запишите ваши реквизиты в файле ~/.pypirc :

[distutils] index-servers = pypi [pypi] username: password:

Все ваш проект готов к публикации. Достаточно ввести соответствующую команду:

$ python setup.py register sdist upload

Вы не сможете опубликовать пакет helloworld , тк данное имя проекта уже занято.

setup.py

Сценарий установки является центром всей деятельности по созданию, распространению и установке модулей с использованием Distutils. Его цель — правильная установка программного обеспечения.

Если все, что вам нужно, это распространить модуль с именем foo, содержащийся в файле foo.py, то ваш скрипт установки может быть таким простым:

 from distutils.core import setup setup(name='foo', version='1.0', py_modules=['foo'], ) 

Чтобы создать исходный дистрибутив для этого модуля, вы должны создать скрипт установки setup.py, содержащий приведенный выше код, и запустить эту команду из терминала:

 python setup.py sdist 

sdist создаст архивный файл (например, tarball в Unix, ZIP-файл в Windows), содержащий ваш скрипт установки setup.py и ваш модуль foo.py. Архивный файл будет называться foo-1.0.tar.gz (или .zip) и будет распакован в каталог foo-1.0.

Если конечный пользователь желает установить ваш модуль foo, все, что ему нужно сделать, это загрузить foo-1.0.tar.gz (или .zip), распаковать его и — из каталога foo-1.0 — запустить

 python setup.py install 

Добавление сценариев командной строки в ваш пакет Python

Скрипты командной строки внутри пакетов Python являются общими. Вы можете организовать свой пакет таким образом, чтобы, когда пользователь установит пакет, скрипт был доступен по его пути.

Если вы имели greetings пакета , который имел в командной строке скрипт hello_world.py .

 greetings/ greetings/ __init__.py hello_world.py 

Вы можете запустить этот скрипт, запустив:

 python greetings/greetings/hello_world.py 

Однако, если вы хотите запустить его так:

 hello_world.py 

Вы можете достичь этого путем добавления scripts к вашей setup() в setup.py , как это:

 from setuptools import setup setup( name='greetings', scripts=['hello_world.py'] ) 

При установке пакета приветствия теперь hello_world.py будет добавлен к вашему пути.

Другой возможностью было бы добавить точку входа:

 entry_points=

Таким образом, вы просто должны запустить его так:

 greetings 

Использование метаданных контроля версий в setup.py

setuptools_scm является официально благословенным пакетом , который можно использовать Git или Mercurial метаданные , чтобы определить номер версии пакета, и найти пакеты Python и данные пакета , чтобы включить в него.

 from setuptools import setup, find_packages setup( setup_requires=['setuptools_scm'], use_scm_version=True, packages=find_packages(), include_package_data=True, ) 

Этот пример использует обе функции; только использовать метаданные SCM для версии, замените вызов find_packages() с ручным списком пакетов, или использовать только пакет искатель, удалить use_scm_version=True .

Добавление параметров установки

Как видно из предыдущих примеров, основное использование этого скрипта:

 python setup.py install 

Но есть еще больше возможностей, таких как установка пакета и возможность изменить код и протестировать его без необходимости переустановки. Это делается с помощью:

 python setup.py develop 

Если вы хотите , чтобы выполнять определенные действия , как составление документации сфинкса или строительство FORtran кода, вы можете создать свой собственный вариант , как это:

 cmdclasses = dict() class BuildSphinx(Command): """Build Sphinx documentation.""" description = 'Build Sphinx documentation' user_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): import sphinx sphinx.build_main(['setup.py', '-b', 'html', './doc', './doc/_build/html']) sphinx.build_main(['setup.py', '-b', 'man', './doc', './doc/_build/man']) cmdclasses['build_sphinx'] = BuildSphinx setup( . cmdclass=cmdclasses, ) 

initialize_options и finalize_options будут выполняться до и после run функции , как их имена предполагает его.

После этого вы сможете назвать свой вариант:

 python setup.py build_sphinx 

Как вручную установить пакет в Python

Большинство пакетов в Python сейчас спроектированы так, чтобы быть совместимыми с менеджером пакетов pip. Но что если у вас есть пакеты, несовместимые с pip, и вам нужно установить пакет вручную? Сегодня мы разберем, как это делается.

Примечание редакции Pythonist: об установке пакетов через менеджер читайте в статье «Установка пакетов Python при помощи PIP».

  1. Загрузите пакет и извлеките его в локальный каталог.
  2. Если пакет включает в себя собственный набор инструкций по установке, следуйте им. В противном случае наиболее распространенным методом ручной установки пакета является реализация setup.py .

Установка пакетов Python с помощью setup.py

Чтобы установить пакет, содержащий файл setup.py , откройте командную строку или окно терминала и сделайте следующее:

  1. С помощью команды cd переместитесь в каталог, где находится файл setup.py
  2. Введите следующую команду: python setup.py install

Среда сборки setup.py

Пакеты, устанавливаемые при помощи setup.py, имеют требования относительно среды сборки, которые разработчики должны учитывать. Но некоторые требования опциональны.

Примеры

С помощью следующей команды проверьте, что у вас установлена ​​актуальная версия setuptools:

python -m pip install —upgrade setuptools

Включите именованные аргументы install_requires в setup.py . Отметим, что install_requires — это ключевое слово setuptools , используемое для указания минимальных требований к пакету. Например, это может выглядеть следующим образом:

install_requires=[»], # опциональное ключевое слово

Полные требования к сборке пакета для установки на основе setup.py изложены PyPA (Python Packaging Authority) в «Sample Project».

Sample Project

Sample Project — это пакет-шаблон с файлом setup.py для ручной установки пакета. Файл снабжен аннотациями, касающимися настройки скрипта и среды сборки пакета в целом. Sample Project можно найти на GitHub.

Основан Sample project на пакете setuptools. setup.py — это скрипт сборки для пакетов, созданных с помощью setuptools .

Пример setup.py (без аннотаций):

import setuptools with open("README.md", "r") as fh: long_description = fh.read() setuptools.setup( name , # Replace with your username version="1.0.0", author , author_email , description , long_description=long_description, long_description_content_type="text/markdown", url , packages=setuptools.find_packages(), classifiers=[ "Programming Language :: Python :: 3", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", ], python_requires='>=3.6', )

Заключение

Итак, сегодня мы разобрали, как вручную установить пакеты в Python. А именно — как это сделать с помощью setup.py.

Надеемся, данная статья была вам полезна! Успехов в написании кода!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *