Introduction
This tutorial is for programmers who are encountering the ModuleNotFoundError: No module named 'distutils'
when trying to import skfuzzy
in a Python 3.12 environment. The error occurs because Python 3.12 does not include the distutils
module by default, as it was deprecated in Python 3.10 and removed in 3.12.
Why Distutils is Important
distutils
is a set of tools for creating, installing, and managing Python packages. It is used to build and package Python modules and packages, including skfuzzy
. Although Python 3.12 does not include the distutils
module by default, it is still possible to use it by installing setuptools
.
To install setuptools
, you can use the following command:
pip install setuptools
After installing setuptools
, you can use it to install distutils
by running the following command:
setuptools install distutils
This command will install the distutils
module in your Python environment.
Conclusion
In conclusion, to install distutils
on Python 3.12, you need to install setuptools
and then use setuptools
to install distutils
. This tutorial provides a step-by-step guide on how to do this, and it should help you avoid the ModuleNotFoundError
when trying to import skfuzzy
in a Python 3.12 environment.
- Автор
-
Грег Уорд
Примечание
Весь пакет distutils
был устаревшим и будет удален в Python 3.12. Эта документация сохраняется только в качестве справочного материала и будет удалена вместе с пакетом. Для получения дополнительной информации см. запись What’s New.
См.также
- Установка модулей Python
-
Актуальная документация по установке модуля. Для регулярного использования Python вам почти наверняка понадобится этот документ, а не этот.
Примечание
В этом руководстве рассматриваются только основные инструменты для создания и распространения расширений, которые поставляются в составе данной версии Python. Сторонние инструменты предлагают более простые в использовании и более безопасные альтернативы. За дополнительной информацией обращайтесь к quick recommendations section в руководстве пользователя по упаковке Python.
Введение¶
В Python 2.0 API distutils
был впервые добавлен в стандартную библиотеку. Это обеспечило разработчиков дистрибутивов Linux стандартным способом преобразования проектов Python в пакеты дистрибутивов Linux, а системных администраторов — стандартным способом их установки непосредственно на целевые системы.
За многие годы, прошедшие после выхода Python 2.0, тесная связь системы сборки и установщика пакетов с циклом выпуска среды выполнения языка оказалась проблематичной, и теперь рекомендуется, чтобы проекты использовали установщик пакетов pip
и систему сборки setuptools
, а не напрямую distutils
.
Более подробную информацию смотрите в Установка модулей Python и Распространение модулей Python.
Эта устаревшая документация сохраняется только до тех пор, пока мы не будем уверены, что документация setuptools
охватывает все необходимое.
Дистрибутивы с исходным кодом на основе Distutils¶
Если вы скачаете дистрибутив с исходным кодом модуля, вы можете довольно быстро определить, был ли он упакован и распространен стандартным способом, т.е. с помощью Distutils. Во-первых, название дистрибутива и номер версии будут указаны в названии загруженного архива, например, foo-1.0.tar.gz
или widget-0.9.7.zip
. Затем архив распакуется в каталог с аналогичным названием: foo-1.0
или widget-0.9.7
. Кроме того, дистрибутив будет содержать установочный скрипт setup.py
и файл с именем README.txt
или, возможно, просто README
, который должен объяснить, что сборка и установка дистрибутива модуля — это простое дело выполнения одной команды из терминала:
Для Windows эту команду следует выполнить из окна командной строки ():
Если все это так, то вы уже знаете, как собрать и установить модули, которые вы только что загрузили: Выполните приведенную выше команду. Если вам не нужно устанавливать модули нестандартным способом или настраивать процесс сборки, вам не нужно это руководство. Вернее, приведенная выше команда — это все, что вам нужно получить от этого руководства.
Стандартная сборка и установка¶
Как описано в разделе Дистрибутивы с исходным кодом на основе Distutils, сборка и установка дистрибутива модуля с помощью Distutils обычно сводится к выполнению одной простой команды из терминала:
Варианты платформ¶
Вы всегда должны запускать команду setup из корневого каталога дистрибутива, т.е. из подкаталога верхнего уровня, в который распаковывается исходный дистрибутив модуля. Например, если вы только что загрузили исходный дистрибутив модуля foo-1.0.tar.gz
на Unix-систему, обычным действием будет следующее:
gunzip -c foo-1.0.tar.gz | tar xf - # unpacks into directory foo-1.0 cd foo-1.0 python setup.py install
В Windows вы, вероятно, загрузите foo-1.0.zip
. Если вы скачали архивный файл по адресу C:\Temp
, то он распакуется в C:\Temp\foo-1.0
; для распаковки архива можно использовать либо архивный манипулятор с графическим интерфейсом пользователя (например, WinZip), либо инструмент командной строки (например, unzip или pkunzip). Затем откройте окно командной строки и выполните:
cd c:\Temp\foo-1.0 python setup.py install
Разделение работы на части¶
Выполнение команды setup.py install
приводит к сборке и установке всех модулей за один запуск. Если вы предпочитаете работать постепенно — особенно полезно, если вы хотите настроить процесс сборки, или если что-то идет не так — вы можете использовать сценарий установки для выполнения одного действия за раз. Это особенно полезно, когда сборка и установка будут выполняться разными пользователями — например, вы можете захотеть собрать дистрибутив модуля и передать его системному администратору для установки (или сделать это самостоятельно, с привилегиями суперпользователя).
Например, вы можете собрать все за один шаг, а затем установить все за второй шаг, вызвав сценарий установки дважды:
python setup.py build python setup.py install
Если вы сделаете это, вы заметите, что выполнение команды install сначала запускает команду build, которая — в данном случае — быстро замечает, что ей нечего делать, поскольку все в каталоге build
обновлено.
Возможно, вам не часто понадобится эта способность разбивать вещи на части, если все, что вы делаете, это устанавливаете модули, скачанные из сети, но она очень удобна для более сложных задач. Если вы займетесь распространением собственных модулей и расширений Python, вы будете использовать множество отдельных команд Distutils самостоятельно.
Как происходит строительство¶
Как подразумевалось выше, команда build отвечает за помещение файлов для установки в каталог сборки. По умолчанию он находится build
под корнем дистрибутива; если вы слишком озабочены скоростью или хотите сохранить дерево исходных текстов в первозданном виде, вы можете изменить каталог сборки с помощью опции --build-base
. Например:
python setup.py build --build-base=/path/to/pybuild/foo-1.0
(Или вы можете сделать это постоянно с помощью директивы в системном или личном конфигурационном файле Distutils; см. раздел Конфигурационные файлы Distutils). Обычно в этом нет необходимости.
По умолчанию дерево сборки имеет следующий вид:
--- build/ --- lib/ or --- build/ --- lib.<plat>/ temp.<plat>/
где <plat>
расширяется до краткого описания текущей платформы ОС/аппаратного обеспечения и версии Python. Первая форма, содержащая только каталог lib
, используется для «чистых дистрибутивов модулей» — то есть, дистрибутивов модулей, включающих только чистые модули Python. Если дистрибутив модуля содержит какие-либо расширения (модули, написанные на C/C++), то используется вторая форма, с двумя каталогами <plat>
. В этом случае каталог temp.plat
содержит временные файлы, созданные в процессе компиляции/линковки, которые на самом деле не устанавливаются. В любом случае, каталог lib
(или lib.plat
) содержит все модули Python (чистый Python и расширения), которые будут установлены.
В будущем будут добавлены дополнительные каталоги для работы со скриптами Python, документацией, двоичными исполняемыми файлами и всем остальным, что необходимо для работы по установке модулей и приложений Python.
Как происходит установка¶
После выполнения команды build (независимо от того, запустили ли вы ее явно или команда install сделала это за вас), работа команды install относительно проста: все, что она должна сделать, это скопировать все, что находится в каталоге build/lib
(или build/lib.plat
) в выбранный вами каталог установки.
Если вы не выбрали каталог установки — то есть, если вы просто запустили setup.py install
— то команда install устанавливает в стандартное место для модулей Python сторонних разработчиков. Это расположение зависит от платформы и от того, как вы собрали/установили сам Python. На Unix (и macOS, которая также основана на Unix) оно также зависит от того, является ли устанавливаемый дистрибутив модулей чистым Python или содержит расширения («нечистый»):
Платформа |
Стандартное место установки |
Значение по умолчанию |
Примечания |
---|---|---|---|
Unix (чистый) |
|
|
(1) |
Unix (нечистый) |
|
|
(1) |
Windows |
|
|
(2) |
Примечания:
-
Большинство дистрибутивов Linux включают Python в качестве стандартной части системы, поэтому
prefix
иexec-prefix
обычно оба/usr
в Linux. Если вы сами собираете Python в Linux (или любой другой Unix-подобной системе), то по умолчаниюprefix
иexec-prefix
будут/usr/local
. -
Каталог установки по умолчанию в Windows был
C:\Program Files\Python
в Python 1.6a1, 1.5.2 и более ранних версиях.
prefix
и exec-prefix
означают каталоги, в которые устанавливается Python и где он находит свои библиотеки во время выполнения. Они всегда одинаковы в Windows, и очень часто одинаковы в Unix и macOS. Вы можете узнать, что ваша установка Python использует для prefix
и exec-prefix
, запустив Python в интерактивном режиме и набрав несколько простых команд. В Unix просто введите python
в приглашении оболочки. В Windows выберите . После запуска интерпретатора вы набираете код Python в подсказке. Например, на моей системе Linux я набираю три оператора Python, показанные ниже, и получаю вывод, как показано на рисунке, чтобы узнать мои prefix
и exec-prefix
:
Python 2.4 (#26, Aug 7 2004, 17:19:02) Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> sys.prefix '/usr' >>> sys.exec_prefix '/usr'
В этом документе используется еще несколько условных обозначений: X.Y
обозначает версию Python, например 3.2
; abiflags
будет заменено значением sys.abiflags
или пустой строкой для платформ, не определяющих флаги ABI; distname
будет заменено именем устанавливаемого дистрибутива модуля. Точки и капитализация важны в путях; например, значение, использующее python3.2
на UNIX, обычно будет использовать Python32
на Windows.
Если вы не хотите устанавливать модули в стандартное место, или у вас нет прав на запись, то вам нужно прочитать об альтернативных установках в разделе Альтернативная установка. Если вы хотите сильнее настроить каталоги установки, смотрите раздел Индивидуальная установка о пользовательских установках.
Альтернативная установка¶
Часто бывает необходимо или желательно установить модули в место, отличное от стандартного расположения сторонних модулей Python. Например, в системе Unix у вас может не быть разрешения на запись в стандартный каталог модулей сторонних разработчиков. Или вы можете захотеть опробовать модуль, прежде чем сделать его стандартной частью вашей локальной установки Python. Это особенно актуально при обновлении уже имеющегося дистрибутива: вы хотите убедиться, что существующая база скриптов будет работать с новой версией, прежде чем приступать к обновлению.
Команда Distutils install предназначена для простой и безболезненной установки дистрибутивов модулей в другое место. Основная идея заключается в том, что вы указываете базовый каталог для установки, а команда install выбирает набор каталогов (называемый схемой установки) в этом базовом каталоге, в которые нужно установить файлы. Детали отличаются на разных платформах, поэтому читайте те разделы, которые относятся к вам.
Обратите внимание, что различные альтернативные схемы установки являются взаимоисключающими: вы можете передать --user
, или --home
, или --prefix
и --exec-prefix
, или --install-base
и --install-platbase
, но вы не можете смешивать из этих групп.
Альтернативная установка: схема пользователя¶
Эта схема разработана как наиболее удобное решение для пользователей, которые не имеют права записи в глобальный каталог site-packages или не хотят устанавливать в него. Она включается с помощью простой опции:
python setup.py install --user
Файлы будут установлены в подкаталоги каталога site.USER_BASE
(далее записывается как userbase
). Эта схема устанавливает модули чистого Python и модули расширения в одно и то же место (также известное как site.USER_SITE
). Вот значения для UNIX, включая macOS:
Тип файла |
Каталог установки |
---|---|
модули |
|
скрипты |
|
данные |
|
Заголовки C |
|
А вот значения, используемые в Windows:
Тип файла |
Каталог установки |
---|---|
модули |
|
скрипты |
|
данные |
|
Заголовки C |
|
Преимущество использования этой схемы по сравнению с другими, описанными ниже, заключается в том, что каталог site-packages пользователя при нормальных условиях всегда включен в sys.path
(см. site
для получения дополнительной информации), что означает отсутствие дополнительных действий, которые необходимо выполнить после запуска сценария setup.py
для завершения установки.
Команда build_ext также имеет опцию --user
для добавления userbase/include
в путь поиска заголовочных файлов компилятора и userbase/lib
в путь поиска библиотек компилятора, а также в путь поиска разделяемых библиотек Си во время выполнения (rpath).
Альтернативная установка: схема дома¶
Идея «домашней схемы» заключается в том, что вы создаете и поддерживаете личный тайник модулей Python. Название этой схемы происходит от идеи «домашнего» каталога в Unix, поскольку для пользователей Unix не редкость, когда их домашний каталог имеет расположение, похожее на /usr/
или /usr/local/
. Эта схема может быть использована любым пользователем, независимо от операционной системы, для которой он устанавливает программу.
Установить новый дистрибутив модуля так же просто, как
python setup.py install --home=<dir>
где для опции --home
вы можете указать любой каталог, который вам нравится. На Unix ленивые машинистки могут просто набрать тильду (~
); команда install расширит ее до вашего домашнего каталога:
python setup.py install --home=~
Чтобы заставить Python найти дистрибутивы, установленные по этой схеме, вам, возможно, придется modify Python’s search path или отредактировать sitecustomize
(см. site
), чтобы вызвать site.addsitedir()
или отредактировать sys.path
.
Опция --home
определяет базовый каталог установки. Файлы устанавливаются в следующие каталоги под базой установки следующим образом:
Тип файла |
Каталог установки |
---|---|
модули |
|
скрипты |
|
данные |
|
Заголовки C |
|
(Мысленно замените слеши на обратные слеши, если вы работаете в Windows).
Альтернативная установка: Unix (префиксная схема)¶
Префиксная схема» полезна, когда вы хотите использовать одну установку Python для выполнения сборки/установки (т.е. для запуска сценария установки), но установить модули в каталог сторонних модулей другой установки Python (или чего-то, что похоже на другую установку Python). Если это звучит несколько необычно, то так оно и есть — именно поэтому схемы user и home идут впереди. Однако есть как минимум два известных случая, когда префиксная схема будет полезна.
Во-первых, учтите, что многие дистрибутивы Linux помещают Python в /usr
, а не в более традиционный /usr/local
. Это вполне уместно, поскольку в таких случаях Python является частью «системы», а не локальным дополнением. Однако, если вы устанавливаете модули Python из исходного кода, вы, вероятно, захотите, чтобы они находились в /usr/local/lib/python2.X
, а не в /usr/lib/python2.X
. Это можно сделать с помощью
/usr/bin/python setup.py install --prefix=/usr/local
Другой возможностью является сетевая файловая система, в которой имя, используемое для записи в удаленный каталог, отличается от имени, используемого для чтения: например, интерпретатор Python, доступный как /usr/local/bin/python
, может искать модули в /usr/local/lib/python2.X
, но эти модули должны быть установлены, скажем, в /mnt/@server/export/lib/python2.X
. Это можно сделать с помощью
/usr/local/bin/python setup.py install --prefix=/mnt/@server/export
В любом случае, опция --prefix
определяет базу установки, а опция --exec-prefix
определяет платформо-специфическую базу установки, которая используется для специфических для платформы файлов. (В настоящее время это означает только дистрибутивы нечистых модулей, но может быть расширено до библиотек C, двоичных исполняемых файлов и т.д.) Если параметр --exec-prefix
не указан, то по умолчанию используется --prefix
. Файлы устанавливаются следующим образом:
Тип файла |
Каталог установки |
---|---|
Модули Python |
|
модули расширения |
|
скрипты |
|
данные |
|
Заголовки C |
|
Нет требования, чтобы --prefix
или --exec-prefix
действительно указывали на альтернативную установку Python; если перечисленные выше каталоги еще не существуют, они создаются во время установки.
Кстати, реальная причина важности префиксной схемы заключается в том, что стандартная установка Unix использует префиксную схему, но с --prefix
и --exec-prefix
, поставляемыми самим Python как sys.prefix
и sys.exec_prefix
. Таким образом, вы можете думать, что никогда не будете использовать префиксную схему, но каждый раз, когда вы запускаете python setup.py install
без каких-либо других опций, вы используете ее.
Обратите внимание, что установка расширений в альтернативную установку Python не влияет на способ сборки расширений: в частности, заголовочные файлы Python (Python.h
и друзья), установленные с интерпретатором Python, используемым для запуска сценария установки, будут использоваться при компиляции расширений. Вы должны убедиться, что интерпретатор, используемый для запуска расширений, установленных таким образом, совместим с интерпретатором, используемым для их сборки. Лучший способ сделать это — убедиться, что оба интерпретатора имеют одну и ту же версию Python (возможно, разные сборки, а возможно, копии одной и той же сборки). (Конечно, если ваши --prefix
и --exec-prefix
даже не указывают на альтернативную установку Python, это несущественно).
Альтернативная установка: Windows (префиксная схема)¶
В Windows нет понятия домашнего каталога пользователя, и поскольку стандартная установка Python под Windows проще, чем под Unix, опция --prefix
традиционно используется для установки дополнительных пакетов в отдельные места под Windows.
python setup.py install --prefix="\Temp\Python"
для установки модулей в каталог \Temp\Python
на текущем диске.
База установки определяется опцией --prefix
; опция --exec-prefix
не поддерживается под Windows, что означает, что модули чистого Python и модули расширения устанавливаются в одно и то же место. Файлы устанавливаются следующим образом:
Тип файла |
Каталог установки |
---|---|
модули |
|
скрипты |
|
данные |
|
Заголовки C |
|
Индивидуальная установка¶
Иногда альтернативные схемы установки, описанные в разделе Альтернативная установка, просто не дают того, что вам нужно. Вы можете захотеть изменить только один или два каталога, сохранив все в одном базовом каталоге, или полностью изменить схему установки. В любом случае, вы создаете настраиваемую схему установки.
Чтобы создать пользовательскую схему установки, начните с одной из альтернативных схем и переопределите некоторые каталоги установки, используемые для различных типов файлов, используя эти опции:
Тип файла |
Опция отмены |
---|---|
Модули Python |
|
модули расширения |
|
все модули |
|
скрипты |
|
данные |
|
Заголовки C |
|
Эти параметры переопределения могут быть относительными, абсолютными или явно определенными в терминах одного из базовых каталогов установки. (Существует два базовых каталога установки, и обычно они одинаковы — они различаются только тогда, когда вы используете «префиксную схему» Unix и предоставляете разные опции --prefix
и --exec-prefix
; использование --install-lib
отменяет значения, вычисленные или заданные для --install-purelib
и --install-platlib
, и рекомендуется для схем, которые не делают разницы между Python и модулями расширения).
Например, допустим, вы устанавливаете дистрибутив модуля в свой домашний каталог под Unix — но вы хотите, чтобы скрипты находились в каталоге ~/scripts
, а не ~/bin
. Как и следовало ожидать, вы можете переопределить этот каталог с помощью опции --install-scripts
; в этом случае имеет смысл указать относительный путь, который будет интерпретироваться относительно базового каталога установки (вашего домашнего каталога, в данном случае):
python setup.py install --home=~ --install-scripts=scripts
Другой пример Unix: предположим, что ваша установка Python была собрана и установлена с префиксом /usr/local/python
, поэтому при стандартной установке скрипты будут находиться в каталоге /usr/local/python/bin
. Если вы хотите, чтобы они находились в /usr/local/bin
вместо этого, вы должны указать этот абсолютный каталог для опции --install-scripts
:
python setup.py install --install-scripts=/usr/local/bin
(Это выполняет установку с использованием «префиксной схемы», где префикс — это то, с чем был установлен ваш интерпретатор Python —- /usr/local/python
в данном случае).
Если вы используете Python под Windows, вы можете захотеть, чтобы сторонние модули жили в подкаталоге prefix
, а не прямо в самом prefix
. Это почти так же просто, как настроить каталог установки скриптов — вам просто нужно помнить, что есть два типа модулей, о которых нужно беспокоиться, Python и модули расширений, которые могут удобно управляться одной опцией:
python setup.py install --install-lib=Site
Указанный каталог установки является относительным по отношению к prefix
. Конечно, вы также должны убедиться, что этот каталог находится в пути поиска модулей Python, например, поместив файл .pth
в каталог сайта (см. раздел site
). Смотрите раздел Изменение пути поиска в Python, чтобы узнать, как изменить путь поиска Python.
Если вы хотите определить всю схему установки, вам просто нужно указать все параметры каталога установки. Рекомендуемый способ сделать это — указать относительные пути; например, если вы хотите хранить все файлы, связанные с модулями Python, в домашнем каталоге под python
, и хотите иметь отдельный каталог для каждой платформы, с которой вы используете свой домашний каталог, вы можете определить следующую схему установки:
python setup.py install --home=~ \ --install-purelib=python/lib \ --install-platlib=python/lib.$PLAT \ --install-scripts=python/scripts --install-data=python/data
или, эквивалентно,
python setup.py install --home=~/python \ --install-purelib=lib \ --install-platlib='lib.$PLAT' \ --install-scripts=scripts --install-data=data
$PLAT
не является (обязательно) переменной окружения — она будет расширена Distutils при разборе опций командной строки, так же как и при разборе конфигурационного файла (файлов).
Очевидно, что указывать всю схему установки каждый раз, когда вы устанавливаете новый дистрибутив модуля, было бы очень утомительно. Поэтому вы можете поместить эти опции в ваш конфигурационный файл Distutils (см. раздел Конфигурационные файлы Distutils):
[install] install-base=$HOME install-purelib=python/lib install-platlib=python/lib.$PLAT install-scripts=python/scripts install-data=python/data
или, эквивалентно,
[install] install-base=$HOME/python install-purelib=lib install-platlib=lib.$PLAT install-scripts=scripts install-data=data
Обратите внимание, что эти два параметра не эквивалентны, если при запуске сценария установки вы указываете другой базовый каталог установки. Например,
python setup.py install --install-base=/tmp
установит чистые модули на /tmp/python/lib
в первом случае, и на /tmp/lib
во втором случае. (Для второго случая вы, вероятно, захотите поставить установочную базу /tmp/python
).
Вы, вероятно, заметили использование $HOME
и $PLAT
во входном файле примера конфигурации. Это конфигурационные переменные Distutils, которые имеют большое сходство с переменными окружения. На самом деле, вы можете использовать переменные окружения в конфигурационных файлах на платформах, где есть такое понятие, но Distutils дополнительно определяет несколько дополнительных переменных, которых может не быть в вашем окружении, например $PLAT
. (И, конечно, на системах, где нет переменных окружения, таких как Mac OS 9, конфигурационные переменные, поставляемые Distutils, являются единственными, которые вы можете использовать). Подробнее см. раздел Конфигурационные файлы Distutils.
Примечание
Когда virtual environment активирован, любые опции, изменяющие путь установки, будут игнорироваться из всех конфигурационных файлов distutils, чтобы предотвратить случайную установку проектов за пределами виртуальной среды.
Изменение пути поиска в Python¶
Когда интерпретатор Python выполняет оператор import
, он ищет как код Python, так и модули расширения по пути поиска. Значение пути по умолчанию задается в двоичном файле Python при сборке интерпретатора. Вы можете определить путь, импортировав модуль sys
и распечатав значение sys.path
.
$ python Python 2.2 (#11, Oct 3 2002, 13:31:27) [GCC 2.96 20000731 (Red Hat Linux 7.3 2.96-112)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> sys.path ['', '/usr/local/lib/python2.3', '/usr/local/lib/python2.3/plat-linux2', '/usr/local/lib/python2.3/lib-tk', '/usr/local/lib/python2.3/lib-dynload', '/usr/local/lib/python2.3/site-packages'] >>>
Нулевая строка в sys.path
представляет собой текущий рабочий каталог.
Ожидаемым соглашением для локально установленных пакетов является помещение их в каталог …/site-packages/
, но вы можете захотеть установить модули Python в какой-либо произвольный каталог. Например, на вашем сайте может быть принято хранить все программное обеспечение, связанное с веб-сервером, в каталоге /www
. Тогда дополнительные модули Python могут находиться в /www/python
, а чтобы их импортировать, этот каталог должен быть добавлен в sys.path
. Существует несколько различных способов добавления каталога.
Самый удобный способ — добавить файл конфигурации пути в каталог, который уже есть в пути Python, обычно в каталог .../site-packages/
. Файлы конфигурации пути имеют расширение .pth
, и каждая строка должна содержать один путь, который будет добавлен к sys.path
. (Поскольку новые пути добавляются к sys.path
, модули в добавленных каталогах не будут переопределять стандартные модули. Это означает, что вы не можете использовать этот механизм для установки фиксированных версий стандартных модулей).
Пути могут быть абсолютными или относительными, в этом случае они относятся к каталогу, содержащему файл .pth
. Более подробную информацию смотрите в документации модуля site
.
Несколько менее удобный способ — отредактировать файл site.py
в стандартной библиотеке Python и изменить sys.path
. site.py
автоматически импортируется при выполнении интерпретатора Python, если не установлен переключатель -S
для подавления этого поведения. Поэтому вы можете просто отредактировать site.py
и добавить к нему две строки:
import sys sys.path.append('/www/python/')
Однако, если вы переустановите ту же самую основную версию Python (например, при обновлении с 2.2 до 2.2.2), site.py
будет перезаписана стоковой версией. Вам придется запомнить, что она была изменена, и сохранить копию перед установкой.
Есть две переменные окружения, которые могут изменять sys.path
. PYTHONHOME
задает альтернативное значение для префикса установки Python. Например, если PYTHONHOME
установлена в /www/python
, путь поиска будет установлен в ['', '/www/python/lib/pythonX.Y/', '/www/python/lib/pythonX.Y/plat-linux2', ...]
.
Переменная PYTHONPATH
может быть установлена в список путей, которые будут добавлены к началу sys.path
. Например, если переменная PYTHONPATH
установлена в /www/python:/opt/py
, путь поиска будет начинаться с ['/www/python', '/opt/py']
. (Обратите внимание, что каталоги должны существовать, чтобы быть добавленными к sys.path
; модуль site
удаляет несуществующие пути).
Наконец, sys.path
является обычным списком Python, поэтому любое приложение Python может изменять его, добавляя или удаляя элементы.
Конфигурационные файлы Distutils¶
Как упоминалось выше, вы можете использовать конфигурационные файлы Distutils для записи личных предпочтений или предпочтений сайта для любых опций Distutils. То есть, любой параметр любой команды может быть сохранен в одном из двух или трех (в зависимости от вашей платформы) конфигурационных файлов, которые будут просмотрены перед разбором командной строки. Это означает, что конфигурационные файлы отменяют значения по умолчанию, а командная строка, в свою очередь, отменяет конфигурационные файлы. Более того, если используется несколько конфигурационных файлов, значения из «более ранних» файлов отменяются «более поздними» файлами.
Расположение и имена файлов конфигурации¶
Имена и расположение конфигурационных файлов немного отличаются на разных платформах. На Unix и macOS три конфигурационных файла (в порядке их обработки) следующие:
Тип файла |
Расположение и имя файла |
Примечания |
---|---|---|
система |
|
(1) |
личный |
|
(2) |
местный |
|
(3) |
В Windows конфигурационные файлы находятся:
Тип файла |
Расположение и имя файла |
Примечания |
---|---|---|
система |
|
(4) |
личный |
|
(5) |
местный |
|
(3) |
На всех платформах «личный» файл можно временно отключить, передав опцию –no-user-cfg.
Примечания:
-
Строго говоря, общесистемный конфигурационный файл находится в каталоге, где установлены Distutils; в Python 1.6 и более поздних версиях на Unix это выглядит так, как показано на рисунке. Для Python 1.5.2 Distutils обычно устанавливается в каталог
prefix/lib/python1.5/site-packages/distutils
, поэтому системный конфигурационный файл должен быть помещен туда для Python 1.5.2. -
На Unix, если переменная окружения
HOME
не определена, домашний каталог пользователя будет определен с помощью функцииgetpwuid()
из стандартного модуляpwd
. Это делается с помощью функцииos.path.expanduser()
, используемой Distutils. -
Т.е. в текущем каталоге (обычно это местоположение скрипта настройки).
-
(См. также примечание (1).) В Python 1.6 и более поздних версиях «префикс установки» Python по умолчанию
C:\Python
, поэтому системный конфигурационный файл обычноC:\Python\Lib\distutils\distutils.cfg
. В Python 1.5.2 префикс по умолчанию былC:\Program Files\Python
, а Distutils не был частью стандартной библиотеки — поэтому в стандартной установке Python 1.5.2 под Windows файл системной конфигурации будетC:\Program Files\Python\distutils\distutils.cfg
. -
В Windows, если переменная окружения
HOME
не определена, будет выполнена попыткаUSERPROFILE
, затемHOMEDRIVE
иHOMEPATH
. Это делается функциейos.path.expanduser()
, используемой Distutils.
Синтаксис конфигурационных файлов¶
Все конфигурационные файлы Distutils имеют одинаковый синтаксис. Конфигурационные файлы сгруппированы по разделам. Есть одна секция для каждой команды Distutils, плюс секция global
для глобальных опций, которые влияют на каждую команду. Каждая секция состоит из одной опции в строке, указанной как option=value
.
Например, ниже приведен полный файл конфигурации, который просто заставляет все команды по умолчанию выполняться тихо:
Если этот файл установлен как системный конфигурационный файл, он будет влиять на всю обработку любого дистрибутива модуля Python любым пользователем в текущей системе. Если он установлен как ваш личный конфигурационный файл (на системах, которые их поддерживают), он будет влиять только на дистрибутивы модулей, обрабатываемые вами. А если он используется как setup.cfg
для определенного дистрибутива модуля, то он будет влиять только на этот дистрибутив.
Вы можете переопределить каталог «build base» по умолчанию и заставить команды build* всегда принудительно перестраивать все файлы следующим образом:
[build] build-base=blib force=1
что соответствует аргументам командной строки
python setup.py build --build-base=blib --force
за исключением того, что включение команды build в командную строку означает, что эта команда будет выполнена. Включение определенной команды в конфигурационные файлы не имеет таких последствий; это означает только то, что если команда будет запущена, то будут применены опции, указанные в конфигурационном файле. (Или если будут запущены другие команды, которые получают значения от нее, они будут использовать значения из конфигурационного файла).
Вы можете узнать полный список опций для любой команды, используя опцию --help
, например:
python setup.py build --help
и вы можете узнать полный список глобальных опций, используя --help
без команды:
См. также раздел «Справочник» руководства «Распространение модулей Python».
Строительство пристроек: Советы и рекомендации¶
Когда это возможно, Distutils старается использовать информацию о конфигурации, доступную в интерпретаторе Python, используемом для запуска скрипта setup.py
. Например, те же флаги компилятора и компоновщика, которые используются для компиляции Python, будут использоваться и для компиляции расширений. Обычно это работает хорошо, но в сложных ситуациях это может быть неуместно. В этом разделе рассматривается, как переопределить обычное поведение Distutils.
Настройка флагов компилятора/линкера¶
Компиляция расширения Python, написанного на C или C++, иногда требует указания пользовательских флагов для компилятора и компоновщика, чтобы использовать определенную библиотеку или создать особый вид объектного кода. Это особенно актуально, если расширение не было протестировано на вашей платформе, или если вы пытаетесь кросс-компилировать Python.
В самом общем случае автор расширения мог предвидеть, что компиляция расширений будет сложной, и предоставить файл Setup
для редактирования. Скорее всего, это будет сделано только в том случае, если дистрибутив модуля содержит много отдельных модулей расширений, или если для их работы часто требуется сложный набор флагов компилятора.
Файл Setup
, если он присутствует, разбирается для получения списка расширений для сборки. Каждая строка в Setup
описывает один модуль. Строки имеют следующую структуру:
module ... [sourcefile ...] [cpparg ...] [library ...]
Давайте рассмотрим каждое из полей по очереди.
-
module — это имя собираемого модуля расширения, которое должно быть правильным идентификатором Python. Вы не можете просто изменить это имя, чтобы переименовать модуль (для этого потребуются правки исходного кода), поэтому его следует оставить в покое.
-
sourcefile — это все, что может быть файлом исходного кода, по крайней мере, судя по имени файла. Предполагается, что имена файлов, заканчивающиеся на
.c
, написаны на C, имена файлов, заканчивающиеся на.C
,.cc
и.c++
, — на C++, а имена файлов, заканчивающиеся на.m
или.mm
, — на Objective C. -
cpparg — это аргумент для препроцессора языка C, который представляет собой все, что начинается с
-I
,-D
,-U
или-C
. -
библиотека — это все, что заканчивается на
.a
или начинается на-l
или-L
.
Если на вашей платформе требуется специальная библиотека, вы можете добавить ее, отредактировав файл Setup
и выполнив python setup.py build
. Например, если модуль, определенный строкой
должен быть связан с математической библиотекой libm.a
на вашей платформе, просто добавьте -lm
к строке:
С помощью опций -Xcompiler
arg и -Xlinker
arg можно задать произвольные переключатели, предназначенные для компилятора или компоновщика:
foo foomodule.c -Xcompiler -o32 -Xlinker -shared -lm
Следующая опция после -Xcompiler
и -Xlinker
будет добавлена к соответствующей командной строке, поэтому в приведенном выше примере компилятору будет передана опция -o32
, а компоновщику — -shared
. Если опция компилятора требует аргумента, вам придется предоставить несколько опций -Xcompiler
; например, для передачи -x c++
файл Setup
должен содержать -Xcompiler -x -Xcompiler c++
.
Флаги компилятора также могут быть заданы посредством установки переменной окружения CFLAGS
. Если она установлена, содержимое CFLAGS
будет добавлено к флагам компилятора, указанным в файле Setup
.
Использование компиляторов других производителей под Windows¶
Borland/CodeGear C++¶
В этом подразделе описаны шаги, необходимые для использования Distutils с компилятором Borland C++ версии 5.5. Сначала вы должны знать, что формат объектных файлов Borland (OMF) отличается от формата, используемого в версии Python, которую вы можете загрузить с сайта Python или ActiveState. (Python создан с помощью Microsoft Visual C++, который использует COFF в качестве формата объектных файлов). По этой причине вам необходимо преобразовать библиотеку Python python25.lib
в формат Borland. Это можно сделать следующим образом:
coff2omf python25.lib python25_bcpp.lib
Программа coff2omf
поставляется с компилятором Borland. Файл python25.lib
находится в каталоге Libs
вашей установки Python. Если ваше расширение использует другие библиотеки (zlib, …), вы должны преобразовать и их.
Преобразованные файлы должны находиться в тех же каталогах, что и обычные библиотеки.
Как Distutils удается использовать эти библиотеки с измененными именами? Если расширению нужна библиотека (например, foo
), Distutils сначала проверяет, не найдена ли библиотека с суффиксом _bcpp
(например, foo_bcpp.lib
), а затем использует эту библиотеку. В случае, если такой специальной библиотеки не найдено, используется имя по умолчанию (foo.lib
) 1
Чтобы позволить Distutils скомпилировать ваше расширение с Borland C++, теперь нужно ввести:
python setup.py build --compiler=bcpp
Если вы хотите использовать компилятор Borland C++ по умолчанию, вы можете указать это в персональном или общесистемном конфигурационном файле для Distutils (см. раздел Конфигурационные файлы Distutils).
GNU C / Cygwin / MinGW¶
В этом разделе описаны необходимые шаги для использования Distutils с компиляторами GNU C/C++ в их дистрибутивах Cygwin и MinGW. 2 Для интерпретатора Python, который был собран с помощью Cygwin, все должно работать без каких-либо следующих шагов.
Не все расширения могут быть созданы с помощью MinGW или Cygwin, но многие могут. Скорее всего, не будут работать те расширения, которые используют C++ или зависят от расширений Microsoft Visual C.
Чтобы позволить Distutils скомпилировать ваше расширение с Cygwin, нужно набрать:
python setup.py build --compiler=cygwin
и для Cygwin в режиме no-cygwin 3 или для MinGW тип:
python setup.py build --compiler=mingw32
Если вы хотите использовать какую-либо из этих опций/компиляторов по умолчанию, вам следует прописать это в вашем личном или общесистемном конфигурационном файле для Distutils (см. раздел Конфигурационные файлы Distutils).
Старые версии Python и MinGW¶
Следующие инструкции применимы, только если вы используете версию Python ниже 2.4.1 с MinGW ниже 3.0.0 (с binutils-2.13.90-20030111-1).
Для этих компиляторов требуются некоторые специальные библиотеки. Эта задача сложнее, чем для Borland’s C++, потому что нет программы для преобразования библиотеки. Сначала необходимо создать список символов, которые экспортирует библиотека Python DLL. (Хорошую программу для этой задачи можно найти на сайте https://sourceforge.net/projects/mingw/files/MinGW/Extension/pexports/).
pexports python25.dll >python25.def
Расположение установленного python25.dll
будет зависеть от опций установки, а также от версии и языка Windows. При установке «только для меня» он будет находиться в корне каталога установки. При общей установке он будет находиться в системном каталоге.
Затем вы можете создать из этой информации библиотеку импорта для gcc.
/cygwin/bin/dlltool --dllname python25.dll --def python25.def --output-lib libpython25.a
Полученная библиотека должна быть помещена в тот же каталог, что и python25.lib
. (Это должен быть каталог libs
в каталоге установки Python).
Если ваше расширение использует другие библиотеки (zlib,…), возможно, вам придется конвертировать и их. Конвертированные файлы должны находиться в тех же каталогах, что и обычные библиотеки.
Сноски
- 1
-
Это также означает, что вы можете заменить все существующие COFF-библиотеки на одноименные OMF-библиотеки.
- 2
-
Проверьте https://www.sourceware.org/cygwin/ для получения дополнительной информации
- 3
-
Тогда вам не доступна эмуляция POSIX, но вам также не нужно
cygwin1.dll
.
В прошлый раз мы узнали как создавать модули и пакеты. Сегодня мы возьмём этот пакет и посмотрим, как при помощи distutils мы можем сделать этот пакет доступным для других людей. Мы научимся:
- создавать файл setup.py
- создавать source distribution
- создавать установщик для Windows
Начнём!
Пишем наш первый скрипт “setup.py”
Когда вы пишете ваш скрипт setup.py, Вы должны держать в голове его расположение. Если он будет находиться в папке с вашим пакетом, то это приведёт к ошибке при попытке им воспользоваться. Если он будет расположен где-то далеко, то скорее всего Вы при установке добавите ещё и те файлы, которые бы распространять не хотели. Поэтому для простоты мы создадим новую папку, куда и скопируем созданную вчера папку “mymath”. И тут же сохраним наш setup.py. Структура новой папки будет выглядеть так:
myNewFolder/
mymath/
setup.py
Внимание: Если у Вас нет кода, созданного в прошлой статье, его можно скачать тут
Теперь неплохо бы этот файл наполнить кодом:
from distutils.core import setup setup(name = "mymath", version = "0.1", description = "A Simple Math Package", author = "Mike Driscoll", author_email = "mike@somedomain.com", url = "http://www.blog.pythonlibrary.org/2012/07/08/python-201-creating-modules-and-packages/", packages=["mymath"] )
Что же, выглядит не плохо. Если мы хотим добавить в наш setup.py ещё какие-то пакеты, то мы просто перечисляем их в списке packages. Кроме того есть список py_modules, куда можно добавить отдельные модули. Если Вы будете рыться в документации, то Вы обнаружите, что Вы можете добавлять даже файлы, не являющиеся скриптами Python используя класс Extension библиотеки distutils. Например, это может понадобиться для добавления файлов С или чего-то в этом роде, что можно встретить в сторонних пакетах, вроде lxml.
Distutils: Как распространять исходники и установщики для Windows
После того, как мы сохранили наш файл со скриптом, мы можем создать архив с исходниками, который будет использован для распространения нашего замечательного пакета. Откройте терминал (или командную строку в Windows) и перейдите в созданную вами папку. Затем выполните следующую команду
python setup.py sdist
Вы увидите что-то вроде этого:
C:\Users\mdriscoll\Documents\mymath-setup>python setup.py sdist
running sdist
warning: sdist: manifest template ‘MANIFEST.in’ does not exist (using default file list)
writing manifest file ‘MANIFEST’
creating mymath-0.1
creating mymath-0.1\mymath
copying files to mymath-0.1…
copying README.txt -> mymath-0.1
copying setup.py -> mymath-0.1
copying mymath\__init__.py -> mymath-0.1\mymath
copying mymath\add.py -> mymath-0.1\mymath
copying mymath\divide.py -> mymath-0.1\mymath
copying mymath\multiply.py -> mymath-0.1\mymath
copying mymath\subtract.py -> mymath-0.1\mymath
creating dist
creating ‘dist\mymath-0.1.zip’ and adding ‘mymath-0.1’ to it
adding ‘mymath-0.1\PKG-INFO’
adding ‘mymath-0.1\README.txt’
adding ‘mymath-0.1\setup.py’
adding ‘mymath-0.1\mymath\add.py’
adding ‘mymath-0.1\mymath\divide.py’
adding ‘mymath-0.1\mymath\multiply.py’
adding ‘mymath-0.1\mymath\subtract.py’
adding ‘mymath-0.1\mymath\__init__.py’
creating ‘dist\mymath-0.1.zip’ and adding ‘mymath-0.1’ to it
adding ‘mymath-0.1\PKG-INFO’
adding ‘mymath-0.1\README.txt’
adding ‘mymath-0.1\setup.py’
adding ‘mymath-0.1\mymath\add.py’
adding ‘mymath-0.1\mymath\divide.py’
adding ‘mymath-0.1\mymath\multiply.py’
adding ‘mymath-0.1\mymath\subtract.py’
adding ‘mymath-0.1\mymath\__init__.py’
removing ‘mymath-0.1’ (and everything under it)
Что бы всё это могло значить? Только то, что distutils создал новую папку, названную dist, в которой теперь находится zip файл (mymath-0.1.zip) со всеми файлами вашего пакета. Если же Вы работаете на *nix — то получите tarball.
Далее, если Вы хотите создать установщик под Windows — это тоже будет легко сделать. Вам для этого понадобится такая команда:
python setup.py bdist_wininst
Эта команда создаст папку build (на которую Вы можете не обращать внимание) и файл с названием mymath-0.1.win32.exe в вашей папке dist, который Вы можете запустить под Windows для установки вашего пакета. Так давайте попробуем!
Как установить ваш пакет?
В случае исходников, Вам надо их распаковать / разархивировать и затем выполнить следующую команду:
Если всё было сделано верно и всё работает верно, то пакет будет установлен в вашей системе (для той версии python, которую Вы используете для запуска этой команды — прим. пер.). Если Вы запустите установщик Windows, то возникнет такой мастер установки:
Обратите внимание, что тут показаны все метаданные, которые мы указывали в нашем скрипте setup.py. Круто, правда? В любом случае, если Вы выполните все шаги мастера — Вы опять же установите пакет на свою систему.
Внимание: при такой установке пакет будет установлен в вашу основную версию Python. Если Вы не хотите этого — используйте virtualenv.
Итоги
Теперь Вы должны уметь создавать установщики и устанавливать свои пакеты при помощи distutils. Если Вы хотите загрузить ваш пакет в Python Packages Index (PyPI) — смотрите руководство. Удачи и кодируйте удовольствие!
Чтение на будущее
- Документация по distutils
- Написание setup.py
Источник
Last time we learned how to create modules and packages. Today we’re going to take the package we created and use Python’s distutils to create a couple different ways to distribute our code. In this tutorial, we’ll be learning the following:
- How to create a setup.py file
- How to create a source distribution
- How to create a Windows distribution
Let’s get started!
Writing Our First “setup.py” Script
When you write your setup.py script, you need to be mindful of its location. If you put it inside your package’s folder, you’ll receive an error when you try to build a distribution. And if you put the setup.py file outside of the folder where there’s a bunch of other folders, you’ll probably end up adding a bunch of files you didn’t mean to. So to make this super easy, create a new folder and copy the “mymath” folder we created in the last article into your new folder. Then create your setup.py file in there next to your mymath folder. The folder structure should look something like this:
myNewFolder/ mymath/ setup.py
Note: If you don’t have the code from the last article, you can download it mymath.zip
Now we need to put some code into our new script. Let’s take a look at the following example:
from distutils.core import setup setup(name = "mymath", version = "0.1", description = "A Simple Math Package", author = "Mike Driscoll", author_email = "mike@somedomain.com", url = "https://www.blog.pythonlibrary.org/2012/07/08/python-201-creating-modules-and-packages/", packages=["mymath"] )
Well, that looks pretty straight-forward. If we want to add some more packages to our setup.py file, we’d just add them to the packages list. There’s also a py_modules list that can be added for individual modules. If you go digging in the docs, you will discover that you can add non-Python files too using disutils’ Extension class. This is for including C files or similar, like what is found in 3rd party packages like lxml.
Distutils: How to Build a Source and Windows Distribution
Now that we have our setup script all defined and save, we can create a source archive file that we can use to distribute our fabulous package. Just open up a terminal (or the command line on Windows) and change directories to the new one you created. Then execute the following command:
python setup.py sdist
This should spit out something like this:
C:\Users\mdriscoll\Documents\mymath-setup>python setup.py sdist running sdist warning: sdist: manifest template 'MANIFEST.in' does not exist (using default fi le list) writing manifest file 'MANIFEST' creating mymath-0.1 creating mymath-0.1\mymath copying files to mymath-0.1... copying README.txt -> mymath-0.1 copying setup.py -> mymath-0.1 copying mymath\__init__.py -> mymath-0.1\mymath copying mymath\add.py -> mymath-0.1\mymath copying mymath\divide.py -> mymath-0.1\mymath copying mymath\multiply.py -> mymath-0.1\mymath copying mymath\subtract.py -> mymath-0.1\mymath creating dist creating 'dist\mymath-0.1.zip' and adding 'mymath-0.1' to it adding 'mymath-0.1\PKG-INFO' adding 'mymath-0.1\README.txt' adding 'mymath-0.1\setup.py' adding 'mymath-0.1\mymath\add.py' adding 'mymath-0.1\mymath\divide.py' adding 'mymath-0.1\mymath\multiply.py' adding 'mymath-0.1\mymath\subtract.py' adding 'mymath-0.1\mymath\__init__.py' creating 'dist\mymath-0.1.zip' and adding 'mymath-0.1' to it adding 'mymath-0.1\PKG-INFO' adding 'mymath-0.1\README.txt' adding 'mymath-0.1\setup.py' adding 'mymath-0.1\mymath\add.py' adding 'mymath-0.1\mymath\divide.py' adding 'mymath-0.1\mymath\multiply.py' adding 'mymath-0.1\mymath\subtract.py' adding 'mymath-0.1\mymath\__init__.py' removing 'mymath-0.1' (and everything under it)
What all this means is that distutils has created a new folder named dist that now has a zip file (mymath-0.1.zip) with all your package’s files in it. If you run it on Windows, you get a zip file while on *nix, you’ll get a tarball.
Now if you wanted to create a little Windows installer exe, you can do that too. Just run this slightly different command on the command line:
python setup.py bdist_wininst
This command will create a build directory (which you can ignore) and a file named “mymath-0.1.win32.exe” in your dist folder that you can run on Windows to install your package. Speaking of installing, we should probably try that!
How to Install Your Package
In the case of the source file, you’ll need to unpack / unzip it and then call the following command from your terminal / command line window:
python setup.py install
If everything works correctly, you’ll have a new package installed to your system. To use the Windows exe, you just double-click it and you should see the following wizard appear:
Notice that it displays all that metadata we created in our setup.py script. Isn’t that cool? Anyway, if you run through the installer, it should install the package too.
NOTE: Doing the installation this way will add this package to your base Python installation. If you would rather not do that, then you could use virtualenv for your testbed.
Wrapping Up
At this point, you should be able to create and install your own package using distutils and Python. If you want to upload your package to the Python Packages Index (PyPI), then you should read their tutorial. Good luck and happy coding!
Further Reading
- Disutils official documentation
- Writing a setup script
Introduction
This tutorial will cover setuptools
and how to package libraries and applications
for pip
, https://pypi.org, and distribution to others.
- setuptools package
- setuptools documentation
These examples will show you how to create distributable packages. We’ll look at how import works, how the setup.py file and how to use it to build and install packages. I recommend creating a new virtual environment and activating it before testing out any of these examples. If you aren’t familiar, read up on virtual environments. That will ensure you have an isolated environment do not contaminate your system install or any project. You can also get started with a simple distutils example from the official documentation. See my Python Virtual Environments Tutorial if you need to learn more about virtual environments.
Also see Python import, sys.path, and PYTHONPATH Tutorial
and my Python Virtual Environment Tutorial.
If you need Python, check out my tutorials:
- Installing Python 3 on MacOS
- How to build Python from Source
Terminology
Before going any further, let’s look at some terms that might be confusing:
- Module — A Python file (.py) with code, functions, classes, etc.
- Package — A directory with Python modules files. Might have an init.py and/or main.py along with Python modules (.py files). The word package also commonly refers to a distributable package.
- Distributable package — A Python library or application that was pacakged with a setup.py file that is built in to a distributable file that can be published on PyPI.org. This term may be shortened to just «package» which can cause confusion between the other use of the word package which refers to a directory with Python modules. Even in this tutorial, I may refer to a distribution as a «package» and when dicussing «packaging» it refers to creating a distributable.
- setuptools — The python package used to create and manage distributable Python packages.
- distutils — The older version of setuptools, which is now legacy. Use setuptools instead.
- setup.py — The primary file of a distributable package that defines author, version information, files to include, etc. Used to build, install, and upload the package it belongs to. Builds packages that can be installed using pip. Functions provided by distutils package.
- pip — Tool for downloading, installing, uninstalling, upgrading distirubted packages in a Python instance. Works with packages built using setuptools and setup.py.
- PyPI — Python Package Index, pypi.org — the public repository for Python packages.
Minimal package
This is the simplest possible package that you can build and install. I would never recommend making a package like this, but it demonstrates the core element of a distributable package, the setup.py file.
This example will default to version 0.0.0, have no author information, and in general, is not fit for sharing. Technically it will work and you can install modules to your local site-packages for re-use but again, this is only an example for learning. Read the next section for how to make a better package.
All you really need to do to turn your regular package in to a package ready for distribution is add a setup.py file.
The setup.py file defines the package name, version number, author information, files, and any additional setup.
All of the magic comes with this setup.py file. This is a really simple setup.py example, taken from, https://docs.python.org/3.7/distutils/introduction.html#distutils-simple-example. Other useful resources include an example pypi project or the setup script documentation.
Note that if you just want to create a package for use locally in a single project, you do not need a setup.py and do not need to create a distributable package. This describes the process for building a package that is intended to be installed to your Python site-packages for use among multiple projects or shared with other people.
# Directory structure
\ # Project directory root
\setup.py # Describes distributable package info
\mylib.py # Contains the python code for sharing
# setup.py
from setuptools import setup
setup(
name='my_module',
py_modules=['my_module'], # Include my_module.py
)
The example above shows the simples possible distributable package you can make. It may not make it up to pypi.org but it will technically install locally. All you need is a single .py file (your module) and a setup.py to provide the name and list of modules to include. With this, you can run python setup.py install and it will install the module to your site-packages directory.
python setup.py install
When you install it, the package will be copied in to your site packages
directory making your package available for import. To learn more
about import
, sys.path
, PYTHONPATH
and how Python searches
for modules to import, check out my Python import, sys.path, and PYTHONPATH Tutorial
.
Then you would import it like this in a Python script:
import my_module
Install versus develop
python setup.py install
# or
python setup.py develop
# develop will create symlinks so it doesn't require reinstall after every change
# This works in Windows too!
See other setup.py commands with:
python setup.py --help-commands
Create a distribution package
There are different distribution options. The simplest option is the source
distribution (sdist
) where it simply packages up all the source code.
Other packages can be built using a build distribution (bdist
) which
are good for packages with binary blobs or creating a special format.
Some options include rpm
and msi
for Linux packages and Windows
installers!
pip install twine # tool to push to pypi
python setup.py sdist # Package the release file
twine upload dist/<package_file>
# Other package options
python setup.py bdist --format=gztar # .tar.gz
python setup.py bdist --format=zip # .zip
python setup.py bdist --format=rpm # Yum package (Fedora/CentOS/RHEL)
python setup.py bdist --format=msi # Windows installer
python setup.py bdist --format=wininst # self extracting zip
Push package to PyPI.org
To update your package and push it to pypi, update your setup.py
to
make the version number higher than the current version, and repackage
with python setup.py sdist
. Follow that up with a twine upload
.
# Build the package
python setup.py sdist
# Upload the package
twine upload dist/mypackage.tar.gz
Set up \~/.pypirc
When using twine
to upload, for example,
twine upload dist/mypackage-1.0.0.tar.gz
,
you can avoid entering your password
each time by setting up a ~/.pypirc
file.
This step is optional, but if you upload packages to pypi.org regularly,
this will save a lot of time.
Here is an example:
# ~/.pypirc
[distutils]
index-servers=pypi
[pypi]
# repository = https://upload.pypi.org/legacy/
username = myusername
password = mysecretpassword
Name the file .pypirc
and place it in your $HOME
directory.
Create a distributable package
This will explain how to package a Python application for sharing on pypi.org
that can be installed with pip
. Another method of packaging an application
is to create a standalone .exe, .app, or Linux executable. You can use PyInstaller
to do this. If you are interested in that, check out my PyInstaller tutorial.
The previous example is an absolute minimum. It didn’t have any author or version information about the module. You can provide a lot more useful information in the setup.py file. Not only can you provide links to a website or documentation, you can specify executable scripts that should be installed with your module and dependencies that it relies on. This example is a better template for a new package.
# Directory structure
\
\README.rst # Simple documentation
\setup.py # Used to build package and install
\mypackage\__init__.py # Executed when package is imported (optional)
\mypackage\__main__.py # Executed with python -m mypackage (optional)
\mypackage\mymodule1.py # Modules the package provides/uses
\mypackage\mymodule2.py # Modules the package provides/uses
That’s the core of a basic package. You do not have to create a package and can simply provide modules as demonstarted in the first example. In the setup.py file you have options for py_modules to include and packages to include. For more information about what you can provide in the setup.py file check out the official documentation on the setup script.
Add executable scripts
Option 1) Add scripts
Option 2) Use entrypoint
When addding executable scripts to a package, I recommend placing them in a bin/
directory. Then, in the setup.py
file, provide the list of scripts to the scripts
parameter.
. Create a .bat file for Windows and a shell script with a shebang for Linux/Mac. Refer to the examples provided for how to build the scripts.
Entrypoints (scripts)
From https://setuptools.readthedocs.io/en/latest/setuptools.html#automatic-script-creation
Packaging and installing scripts can be a bit awkward with the distutils. For one thing, there’s no easy way to have a script’s filename match local conventions on both Windows and POSIX platforms. For another, you often have to create a separate file just for the “main” script, when your actual “main” is a function in a module somewhere. And even in Python 2.4, using the -m option only works for actual .py files that aren’t installed in a package.
setuptools fixes all of these problems by automatically generating scripts for you with the correct extension, and on Windows it will even create an .exe file so that users don’t have to change their PATHEXT settings. The way to use this feature is to define “entry points” in your setup script that indicate what function the generated script should import and run. For example, to create two console scripts called foo and bar, and a GUI script called baz, you might do something like this:
setup(
# other arguments here...
entry_points={
'console_scripts': [
'foo = my_package.some_module:main_func',
'bar = other_module:some_func',
],
'gui_scripts': [
'baz = my_package_gui:start_func',
]
}
)
PyInstaller is another option for packaging applications for distribution.
PyInstaller lets you create Windows .exe
, Mac .app
, and Linux
executable files. You can even have it package as a single file.
You can follow my PyInstaller tutorial here:
https://www.devdungeon.com/content/pyinstaller-tutorial.
scripts vs entry_points
Example setup.py template
Here is an example setup.py
that you can use a starting place for your own package.
Remove any pieces you don’t need and modify everything else.
# setup.py template
# https://docs.python.org/3/distutils/setupscript.html
import os
from setuptools import setup
from sys import platform
requirements = [
'docopt',
'discord.py==0.16.12'
]
if platform == "win32":
requirements.append('windows-curses')
setup(
name = "an_example_pypi_project",
version = "0.0.4",
author = "Andrew Carter",
author_email = "andrewjcarter@gmail.com",
description = ("An demonstration of how to create, document, and publish "
"to the cheese shop a5 pypi.org."),
license = "MIT",
keywords = "example documentation tutorial",
url = "http://packages.python.org/an_example_pypi_project",
# Individual Python modules (.py files)
py_modules=['mymodule'],
# Directories (package)
packages=[
'mypackage',
'tests'
],
long_description_content_type='text/markdown',
long_description=open('README.md').read(),
scripts=scripts,
package_data={ # Other misc files that should be installed
'mypackage': [
'data/defaults.xml', # Relative to setup.py dir
'data/*.dat',
],
},
python_requires='<3.7', # Optional
install_requires=requirements,
platforms='any',
classifiers=[ # Options at https://pypi.org/classifiers/
'Development Status :: 4 - Beta',
'Environment :: Console :: Curses',
'Environment :: Web Environment',
'Environment :: MacOS X',
'Environment :: X11 Applications :: Qt',
'Framework :: Django :: 2.1',
'Framework :: Flask',
'Intended Audience :: End Users/Desktop',
'Intended Audience :: Developers',
'Intended Audience :: System Administrators',
'Natural Language :: English',
'License :: OSI Approved :: MIT License',
'Operating System :: Android',
'Operating System :: MacOS :: MacOS X',
'Operating System :: Microsoft :: Windows',
'Operating System :: POSIX',
'Programming Language :: Python',
'Topic :: Utilities',
'Topic :: Software Development',
'Topic :: Security',
],
)
You can also add dependencies from GitHub.
Create a standalone .exe, .app, or Linux Executable
If you want to package your application as a standalone executable,
I recommend using PyInstaller. This allows you to easily distribute
your app without the user needing to install or even know anything about Python.
Check out my PyInstaller Tutorial
for more information.
Conclusion
After reading this, you should understand how to create distributable
packages with distutils
using setup.py
. You should be able to create
your own package, add dependencies, include executable scripts, build it,
and upload it to pypi.org for others to download.
References
- https://pypi.org/
- https://pypi.org/project/setuptools/
- https://setuptools.readthedocs.io/en/latest/
- https://docs.python.org/3.7/distutils/introduction.html#distutils-simple-example
- https://pythonhosted.org/an_example_pypi_project/setuptools.html
- https://docs.python.org/3.7/distutils/setupscript.html
- https://docs.python.org/3/library/venv.html
- Python import, sys.path, and PYTHONPATH Tutorial
- https://www.devdungeon.com/content/python-virtual-environments-tutorial
- https://www.devdungeon.com/content/pyinstaller-tutorial
- https://docs.python.org/3.7/distutils/introduction.html#distutils-simple-example
- https://pythonhosted.org/an_example_pypi_project/setuptools.html
- https://docs.python.org/3.7/distutils/setupscript.html
- https://packaging.python.org/discussions/wheel-vs-egg/
- https://www.python.org/dev/peps/pep-0427/