2. Pisanie Skryptu Instalacyjnego

Skrypt instalacyjny jest w centrum wszystkich czynności podczas budowania, rozprowadzania i instalowania modułów przy użyciu Distutils. Głównym zadaniem skryptu instalacyjnego jest opisanie dystrybucji twojego modułu dla Distutils, tak aby różne polecenia które operują na twoich modułach robiły to prawidłowo. Jak widzieliśmy w rozdziale Prosty przykład powyżej, skrypt instalacyjny składa się głównie z wywołania zadania setup(), i większość informacji dostarczonych do Distutils przez twórcę modułu jest dostarczonych jako parametrów kluczowych dla zadania setup().

Tutaj jest trochę bardziej zaangażowany przykład, który będziemy śledzić przez następne parę rozdziałów: własny skrypt instalacyjny Distutils. (Pamiętaj, że chociaż Distutils są zawarte w języku pytonowskim 1.6 i wyższej, Distutils istnieją także niezależnie, tak, że użytkownicy języka pytonowskiego w wersji 1.5.2 mogą używać ich aby zainstalować dystrybucje innych modułów. Własny skrypt instalacyjny Distutils, pokazany tutaj, używany jest tutaj do zainstalowania pakietu dla języka pytonowskiego 1.5.2.)

#!/usr/bin/env python

from distutils.core import setup

setup(name='Distutils',
      version='1.0',
      description='Python Distribution Utilities',
      author='Greg Ward',
      author_email='gward@python.net',
      url='https://www.python.org/sigs/distutils-sig/',
      packages=['distutils', 'distutils.command'],
     )

Istnieją tylko dwie różnice pomiędzy tą i prostą jedno-plikową dystrybucją prezentowaną w rozdziale Prosty przykład: więcej danych, i wyszczególnienie czysto pytonowskich modułów „przez pakiet”, zamiast przez nazwę modułu. Jest to istotne skoro Distutils składają się z paru modułów rozdzielonych na (jak dotejpory) dwa pakiety; jawną listę wszystkich modułów byłaby żmudna w wytworzeniu i trudna w utrzymaniu. Po więcej informacji o dodatkowych danych o danych, sięgnij do rozdziału Dodatkowe dane o danych ( - z ang. - meta-dane - dane o danych).

Zauważ, że jakiekolwiek nazwy ścieżek (plików lub katalogów) dostarczony w skrypcie instalacyjnym powinien być napisany używając konwencji Unixa, tj. separowanej-ukośnikami. Distutils zajmie się zamianą reprezentacji obojętnej wobec maszyny/środowiska zanim użycie ścieżki będzie możliwe. To sprawia że twój skrypt instalacyjny jest przenośny pomiędzy systemami operacyjnymi, co oczywiście jest jednym z głównych celów Distutils. W tym duchu nazwy ścieżek dostępu w tym dokumencie są separowane ukośnikiem.

To rzecz jasna, stosuje się tylko do nazw ścieżek danych dla zadań Distutils. Jeśli na przykład używasz zadań standardowych języka pytonowskiego takich jak glob.glob() lub os.listdir() aby określać pliki, powinieneś uważać aby pisać przenośny kod zamiast go usztywniać w sprawie separatorów ścieżek:

glob.glob(os.path.join('mydir', 'subdir', '*.html'))
os.listdir(os.path.join('mydir', 'subdir'))

2.1. Tworzenie list całych pakietów

The packages option tells the Distutils to process (build, distribute, install, etc.) all pure Python modules found in each package mentioned in the packages list. In order to do this, of course, there has to be a correspondence between package names and directories in the filesystem. The default correspondence is the most obvious one, i.e. package distutils is found in the directory distutils relative to the distribution root. Thus, when you say packages = ['foo'] in your setup script, you are promising that the Distutils will find a file foo/__init__.py (which might be spelled differently on your system, but you get the idea) relative to the directory where your setup script lives. If you break this promise, the Distutils will issue a warning but still process the broken package anyway.

If you use a different convention to lay out your source directory, that’s no problem: you just have to supply the package_dir option to tell the Distutils about your convention. For example, say you keep all Python source under lib, so that modules in the „root package” (i.e., not in any package at all) are in lib, modules in the foo package are in lib/foo, and so forth. Then you would put

package_dir = {'': 'lib'}

w swoim skrypcie instalacyjnym. Kluczami do tego słownika są nazwy pakietów, a nazwa pakietu pustego oznacza pakiet nadrzędny ( - z ang. - dosł. - „root package”). Wartościami są nazwy katalogów względne wobec katalogu głównego dystrybucji. W tym przypadku gdy mówisz packages = ['foo'], składasz obietnicę że plik lib/foo/__init__.py istnieje.

Inną możliwą konwencją jest umieszczenie pakietu foo od razu w katalogu lib, pakietu foo.bar w katalogu lib/bar itd. To byłoby zapisane w skrypcie instalacyjnym jako

package_dir = {'foo': 'lib'}

A package: dir entry in the package_dir dictionary implicitly applies to all packages below package, so the foo.bar case is automatically handled here. In this example, having packages = ['foo', 'foo.bar'] tells the Distutils to look for lib/__init__.py and lib/bar/__init__.py. (Keep in mind that although package_dir applies recursively, you must explicitly list all packages in packages: the Distutils will not recursively scan your source tree looking for any directory with an __init__.py file.)

2.2. Tworzenie list pojedynczych modułów

Dla małej dystrybucji modułu, mógłbyś chcieć wypisać wszystkie moduły zamiast wypisywać pakiety—szczególnie w przypadku pojedynczego modułu, który wchodzi w skład „nadrzędnego pakietu” - z ang. - „root package” (tj. żadnego pakietu wcale). Najprostszy przypadek został pokazany w sekcji Prosty przykład; tutaj jest pokazany trochę bardziej zaangażowany przykład:

py_modules = ['mod1', 'pkg.mod2']

This describes two modules, one of them in the „root” package, the other in the pkg package. Again, the default package/directory layout implies that these two modules can be found in mod1.py and pkg/mod2.py, and that pkg/__init__.py exists as well. And again, you can override the package/directory correspondence using the package_dir option.

2.3. Opisywanie modułów rozszerzających

Tak jak pisanie modułów rozszerzających języka pytonowskiego jest trochę bardziej skomplikowane niż pisanie czystych modułów języka pytonowskiego, opisywanie ich dla Distutils jest trochę bardziej skomplikowane. W przeciwieństwie do modułów czysto pytonowskich, nie wystarczy po prostu wypisać po prostu wszystkich modułów lub pakietów i oczekiwać, że Distutils znajdzie właściwe pliki; musisz określić nazwę rozszerzenia, plik(i) źródłowe, i wszystkie wymagania kompilacji i łączenia plików wynikowych (katalogi załączane, biblioteki z którymi nastąpi łączenie, itd.).

All of this is done through another keyword argument to setup(), the ext_modules option. ext_modules is just a list of Extension instances, each of which describes a single extension module. Suppose your distribution includes a single extension, called foo and implemented by foo.c. If no additional instructions to the compiler/linker are needed, describing this extension is quite simple:

Extension('foo', ['foo.c'])

Uogólnienie Extension może być importowane z modułu distutils.core razem z zadaniem setup(). Zatem skrypt instalacyjny dla dystrybucji modułu, który zawiera tylko to rozszerzenie i nic więcej mógłby wyglądać:

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

Uogólnienie Extension (właściwie leżąca pod spodem machina budowania rozszerzeń wypełniona przez polecenie build_ext daje całkiem sporo możliwości w opisywaniu rozszerzeń języka pytonowskiego, które są opisywane w następnych paragrafach.

2.3.1. Nazwy i pakiety rozszerzeń.

The first argument to the Extension constructor is always the name of the extension, including any package names. For example,

Extension('foo', ['src/foo1.c', 'src/foo2.c'])

opisuje rozszerzenie które przebywa w nadrzędnym pakiecie, podczas gdy:

Extension('pkg.foo', ['src/foo1.c', 'src/foo2.c'])

opisuje tożsame rozszerzenie w pakiecie pkg. Pliki źródłowe i wynikający kod obiektowy są identyczne w obu przypadkach; jedyną różnicą jest gdzie w systemie plików (i stąd też gdzie w hierarchii przestrzeni nazw) wynikające rozszerzenie będzie przebywać.

If you have a number of extensions all in the same package (or all under the same base package), use the ext_package keyword argument to setup(). For example,

setup(...,
      ext_package='pkg',
      ext_modules=[Extension('foo', ['foo.c']),
                   Extension('subpkg.bar', ['bar.c'])],
     )

skompiluje plik foo.c do rozszerzenia pkg.foo, i plik bar.c do pkg.subpkg.bar.

2.3.2. pliki źródłowe rozszerzenia

The second argument to the Extension constructor is a list of source files. Since the Distutils currently only support C, C++, and Objective-C extensions, these are normally C/C++/Objective-C source files. (Be sure to use appropriate extensions to distinguish C++ source files: .cc and .cpp seem to be recognized by both Unix and Windows compilers.)

Jednakże, możesz też załączyć sprzęg plików SWIG (.i) na liście; polecenie build_ext wie jak radzić sobie z rozszerzeniami SWIG: uruchomi SWIG na pliku sprzęgu i skompiluje wynikający plik C/C++ do twojego rozszerzenia.

Pomimo tego ostrzeżenia, opcje dla sprzęgu SWIG mogą być obecnie przekazywane w następujący sposób:

setup(...,
      ext_modules=[Extension('_foo', ['foo.i'],
                             swig_opts=['-modern', '-I../include'])],
      py_modules=['foo'],
     )

Lub w wierszu poleceń w następujący sposób:

> python setup.py build_ext --swig-opts="-modern -I../include"

Na niektórych maszynach/środowiskach, możesz załączyć nie-źródłowe pliki które są przetwarzane przez kompilator i załączane w twoim rozszerzeniu. Obecnie, to po prostu oznacza pliki Windowsowych wiadomości tekstowych (.mc) i definicji zasobów (.rc) dla Visual C++. Te będą skompilowane do plików zasobów binarnych (.res) i połączonych w plik wykonywalny.

2.3.3. Opcje preprocesora

Three optional arguments to Extension will help if you need to specify include directories to search or preprocessor macros to define/undefine: include_dirs, define_macros, and undef_macros.

Dla przykładu, jeśli twoje rozszerzenie wymaga pliku nagłówkowego w katalogu include pod twoim katalogiem nadrzędnym dystrybucji, użyj opcji include_dirs

Extension('foo', ['foo.c'], include_dirs=['include'])

Możesz także określić bezwzględne ścieżki katalogów tutaj; jeśli wiesz że twoje rozszerzenie będzie budowane tylko na systemie Unix-owym z X11R6 zainstalowanym do pliku /usr, może Ci ujść na sucho nawet:

Extension('foo', ['foo.c'], include_dirs=['/usr/include/X11'])

Powinieneś unikać tego rodzaju nie-przenośnego użycia jeśli planujesz rozprowadzać swój kod: jest prawdopodobnie dużo lepiej pisać kod C w następujący sposób

#include <X11/Xlib.h>

If you need to include header files from some other Python extension, you can take advantage of the fact that header files are installed in a consistent way by the Distutils install_headers command. For example, the Numerical Python header files are installed (on a standard Unix installation) to /usr/local/include/python1.5/Numerical. (The exact location will differ according to your platform and Python installation.) Since the Python include directory—/usr/local/include/python1.5 in this case—is always included in the search path when building Python extensions, the best approach is to write C code like

#include <Numerical/arrayobject.h>

Jeśli jednak musisz wstawić katalog załączeń Numerical w całości do twojej ścieżki poszukiwań nagłówków, jednakże, możesz znaleźć ten katalog używając modułu distutils.sysconfig Distutils:

from distutils.sysconfig import get_python_inc
incdir = os.path.join(get_python_inc(plat_specific=1), 'Numerical')
setup(...,
      Extension(..., include_dirs=[incdir]),
      )

Chociaż nawet to jest całkiem przenośne—będzie działać na każdej instalacji języka pytonowskiego, niezależnie od maszyny/środowiska—jest prawdopodobnie dużo łatwiej po prostu napisać twój kod C w rozsądny sposób.

Możesz definiować i odwoływać definicje makropoleceń pre-procesora za pomocą opcji define_macros i undef_macros. define_macros bierze listę (nazwy, wartości) par-krotek, gdzie nazwa jest nazwą makropolecenia do zdefiniowania (ciągiem znaków) i wartość jest jej wartością: albo ciągiem znaków albo None. Definiowanie makropolecenia FOO na None jest równoznaczne czystej definicji #define FOO w twoim kodzie C: w większości kompilatorów, to ustawia FOO na ciąg znaków 1. undef_macros jest po prostu listą makropoleceń do odwołania definicji.

Dla przykładu:

Extension(...,
          define_macros=[('NDEBUG', '1'),
                         ('HAVE_STRFTIME', None)],
          undef_macros=['HAVE_FOO', 'HAVE_BAR'])

jest jednoznaczne z ustawieniem tego ponad każdym plikiem źródłowym C:

#define NDEBUG 1
#define HAVE_STRFTIME
#undef HAVE_FOO
#undef HAVE_BAR

2.3.4. Opcje bibliotek

Możesz także określić biblioteki do dołączenia gdy budujesz swoje rozszerzenie, i katalogi aby poszukiwać tych bibliotek. Opcja biblioteki jest listą bibliotek do łączenia, opcja library_dirs jest listą katalogów do poszukiwania bibliotek w czasie łączenia wynikowego kodu, i runtime_library_dirs jest listą katalogów do poszukiwania współdzielonych (ładowanych dynamicznie) bibliotek w czasie wykonania.

Dla przykładu, jeśli potrzebujesz łączyć z bibliotekami znanymi z tego, że są w standardowej ścieżce poszukiwań w docelowym systemie

Extension(...,
          libraries=['gdbm', 'readline'])

Jeśli musisz podłączyć z bibliotekami w nie-standardowym położeniu, musisz załączyć to położenie w opcji library_dirs:

Extension(...,
          library_dirs=['/usr/X11R6/lib'],
          libraries=['X11', 'Xt'])

(Znów, tego rodzaju nie-przenośnych konstrukcji powinno się unikać jeśli zamierzasz rozprowadzać twój kod.)

2.3.5. Inne opcje

Istnieją wciąż poza tym inne opcje, które mogą być użyte do radzenia sobie ze szczególnymi przypadkami.

The optional option is a boolean; if it is true, a build failure in the extension will not abort the build process, but instead simply not install the failing extension.

The extra_objects option is a list of object files to be passed to the linker. These files must not have extensions, as the default extension for the compiler is used.

extra_compile_args and extra_link_args can be used to specify additional command line options for the respective compiler and linker command lines.

export_symbols is only useful on Windows. It can contain a list of symbols (functions or variables) to be exported. This option is not needed when building compiled extensions: Distutils will automatically add initmodule to the list of exported symbols.

The depends option is a list of files that the extension depends on (for example header files). The build command will call the compiler on the sources to rebuild extension if any on this files has been modified since the previous build.

2.4. Relacje pomiędzy dystrybucją a pakietami

Dystrybucja może odnosić się do pakietów na trzy szczególne sposoby:

  1. Może wymagać pakietów lub modułów.

  2. Może dostarczać pakiety lub moduły.

  3. Może powodować że pakiety lub moduły staną się niepotrzebne.

Te relacje mogą być określane przy użyciu kluczowych parametrów zadania distutils.core.setup().

Zależności od innych modułów pytonowskich i pakietów mogą być określane przez dostarczenie słowa kluczowego requires jako parametru do zadania setup(). Wartość musi być listą ciągów znaków. Każdy ciąg znaków określa pakiet, który jest wymagany, i opcjonalnie które wersje są wystarczające.

Aby określić, że któraś wersja modułu lub pakietu jest wymagana, ciąg znaków powinien składać się w całości z nazwy modułu lub pakietu. Przykłady obejmują 'mojmodul' i 'xml.parsers.expat'.

Jeśli szczególne wersje są wymagane, sekwencja kwalifikatorów może być dostarczona w nawiasach. Każdy kwalifikator może składać się z operatora porównania i numeru wersji. Akceptowane operatory porównania to:

<    >    ==
<=   >=   !=

Te mogą być łączone przez użycie wielu kwalifikatorów rozdzielonych przecinkami (i nadobowiązkowymi znakami białymi). W tym przypadku, wszystkie kwalifikatory muszą się zgadzać; logiczna koniunkcja jest używana do wiązania wyników.

Spójrzmy na wiecheć przykładów:

Wyrażenie wymagania

Wytłumaczenie

==1.0

Tylko wersja 1.0 jest zgodna

>1.0, !=1.5.1, <2.0

Wszystkie wersje po 1.0 i przed 2.0 są zgodne z wyjątkiem 1.5.1

Teraz gdy możemy określić zależności, potrzebujemy także móc określić co dostarczamy a czego inne dystrybucje mogłyby wymagać. To jest dokonywane przy użyciu parametru kluczowego provides dla zadania setup(). Wartość tego słowa kluczowego jest listą ciągów znaków, z których każdy nazywa pytonowski moduł lub pakiet, i dodatkowo (nadobowiązkowo) określa wersję. Jeśli wersja nie jest określona, zakładana jest zgodność wersji z wersją dystrybucji.

Trochę przykładów:

Wyrażenie dostarczania

Wytłumaczenie

mojpakiet

Dostarcza mojpakiet, używając wersji dystrybucji

mojpakiet (1.1)

Dostarcz mojpakiet w wersji 1.1, niezależnie od wersji dystrybucji

Pakiet może deklarować że powoduje że inny pakiet staje się niepotrzebny używając parametru kluczowego obsoletes. Wartość tego jest podobna do tej słowa kluczowego requires: lista ciągów znaków dających wyszczególnienie modułu lub pakietu. Każdy ciąg wyszczególniający składa się z nazwy modułu lub pakietu po której dodatkowo (nadobowiązkowo) występuje jeden lub więcej kwalifikator wersji. Kwalifikatory wersji dane są w nawiasie po nazwie modułu lub pakietu.

Wersje określone przez kwalifikatory to te które stają się zbędne z powodu dystrybucji której dotyczy opis. Jeśli nie są dane żadne kwalifikatory wszystkie wersje nazwanego modułu lub pakietu rozumie się jako zbędne.

2.5. Instalowanie skryptów

Do tej pory zajmowaliśmy się czystymi i nie-czystymi modułami pytonowskimi, które nie są zwykle uruchamiane same przez siebie ale importowane przez skrypty.

Scripts are files containing Python source code, intended to be started from the command line. Scripts don’t require Distutils to do anything very complicated. The only clever feature is that if the first line of the script starts with #! and contains the word „python”, the Distutils will adjust the first line to refer to the current interpreter location. By default, it is replaced with the current interpreter location. The --executable (or -e) option will allow the interpreter path to be explicitly overridden.

The scripts option simply is a list of files to be handled in this way. From the PyXML setup script:

setup(...,
      scripts=['scripts/xmlproc_parse', 'scripts/xmlproc_val']
      )

Zmienione w wersji 3.1: All the scripts will also be added to the MANIFEST file if no template is provided. See Określanie plików do rozprowadzenia.

2.6. Instalowanie danych pakietu

Często dodatkowe pliki konieczne są do zainstalowania dla pakietu. Te pliki są często plikami danych które są blisko związane z wypełnieniem zadań pakietu, lub plikami tekstowymi zawierającymi dokumentację która może być interesująca dla programisty używającego pakietu. Te pliki zwane są danymi pakietu.

Dane pakietu mogą być dodawane do pakietów używając słowa kluczowego package_data - z ang. - danych pakietu parametru dla zadania setup(). Wartość musi być mapowaniem z nazwy pakietu na listę odnoszących się nazw ścieżek które powinny zostać skopiowane do pakietu. Ścieżki są interpretowane jako względne do katalogu zawierającego pakiet (informacja z mapowania package_dir jest używana jeśli jest to właściwe); to jest, pliki oczekiwane są aby były częścią pakietu w katalogach źródłowych. Mogą zawierać znaczniki „globalne” także.

Nazwy ścieżek mogą zawierać porcje katalogów; wszystkie konieczne katalogi zostaną utworzone w instalacji.

Na przykład, jeśli pakiet zawiera podkatalog z wieloma plikami danych, pliki mogą być ułożone w taki sposób w drzewie źródłowym:

setup.py
src/
    mypkg/
        __init__.py
        module.py
        data/
            tables.dat
            spoons.dat
            forks.dat

Odpowiadające wezwanie zadania setup() mogłoby być:

setup(...,
      packages=['mypkg'],
      package_dir={'mypkg': 'src/mypkg'},
      package_data={'mypkg': ['data/*.dat']},
      )

Zmienione w wersji 3.1: All the files that match package_data will be added to the MANIFEST file if no template is provided. See Określanie plików do rozprowadzenia.

2.7. Instalowanie dodatkowych plików

The data_files option can be used to specify additional files needed by the module distribution: configuration files, message catalogs, data files, anything which doesn’t fit in the previous categories.

data_files specifies a sequence of (directory, files) pairs in the following way:

setup(...,
      data_files=[('bitmaps', ['bm/b1.gif', 'bm/b2.gif']),
                  ('config', ['cfg/data.cfg'])],
     )

Each (directory, files) pair in the sequence specifies the installation directory and the files to install there.

Each file name in files is interpreted relative to the setup.py script at the top of the package source distribution. Note that you can specify the directory where the data files will be installed, but you cannot rename the data files themselves.

The directory should be a relative path. It is interpreted relative to the installation prefix (Python’s sys.prefix for system installations; site.USER_BASE for user installations). Distutils allows directory to be an absolute installation path, but this is discouraged since it is incompatible with the wheel packaging format. No directory information from files is used to determine the final location of the installed file; only the name of the file is used.

You can specify the data_files options as a simple sequence of files without specifying a target directory, but this is not recommended, and the install command will print a warning in this case. To install data files directly in the target directory, an empty string should be given as the directory.

Zmienione w wersji 3.1: All the files that match data_files will be added to the MANIFEST file if no template is provided. See Określanie plików do rozprowadzenia.

2.8. Dodatkowe dane o danych

Skrypt instalacyjny może zawierać dodatkowe dane pośrednie poza nazwą i wersją. Te informacje zawierają:

dane-o-danych

Opis

Wartość

Notatki

nazwa

nazwa pakietu

krótki ciąg znaków

(1)

wersja

wersja tego wydania

krótki ciąg znaków

(1)(2)

autor

nazwisko i imie autora pakietu

krótki ciąg znaków

(3)

adres_email_autora

adres email autora pakietu

adres email

(3)

zarządca

imie (i nazwisko) zarządcy pakietu

krótki ciąg znaków

(3)

adres_email_zarządcy

adres email zarządcy pakietu

adres email

(3)

url

adres strony domowej pakietu

URL

(1)

opis

krótki opis podsumowujący pakietu

krótki ciąg znaków

dlugi_opis

dłuższy opis pakietu

długi ciąg znaków

(4)

adres_sciagniecia

miejsce skąd pakiet może być pobrany

URL

klasyfikatory

lista klasyfikatorów

lista ciągów znaków

(6)(7)

maszyny_srodowiska

lista maszyn/środowisk

lista ciągów znaków

(6)(8)

keywords

a list of keywords

lista ciągów znaków

(6)(8)

licencja

licencja pakietu

krótki ciąg znaków

(5)

Uwagi:

  1. Te pola są wymagane.

  2. Jest zalecane aby wersja miała postać major.minor[.patch[.sub]].

  3. Either the author or the maintainer must be identified. If maintainer is provided, distutils lists it as the author in PKG-INFO.

  4. The long_description field is used by PyPI when you publish a package, to build its project page.

  5. Pole licencja - z ang. - license jest tekstem oznaczającym licencję ochraniającą pakiet gdzie licencja nie jest wybrana z klasyfikacji „Licencji” Znaleźnych. Zobacz pole Classifier - klasyfikator. Zauważ, że istnieje opcja dystrybucji licencji która choć jest przestarzała ale wciąż służy jako synonim licencji.

  6. This field must be a list.

  7. The valid classifiers are listed on PyPI.

  8. To preserve backward compatibility, this field also accepts a string. If you pass a comma-separated string 'foo, bar', it will be converted to ['foo', 'bar'], Otherwise, it will be converted to a list of one string.

«short string»

Pojedyncza linia tekstu, nie więcej niż 200 znaków.

«long string»

Multiple lines of plain text in reStructuredText format (see http://docutils.sourceforge.net/).

«list of strings»

Zob poniżej.

Kodowanie informacji o wersji jest sztuką samą w sobie. Pakiety języka pytonowskiego zwykle stosują się do formatu wersji główna.poboczna[.łatka][pod]. Główny numer jest 0 w początkowych eksperymentalnych wydaniach oprogramowania. Jest zwiększane dla wydań, które reprezentują główne kroki milowe w pakiecie. Liczba poboczna jest zwiększana gdy istotne nowe własności są dodawane do pakietu. Numer łatki zwiększa się gdy naprawy błędów są robione. Dodatkowe informacje o wersji kończące są czasem używane do zaznaczenia pod-wydań. To są „a1,a2,…,aN” (dla wydań alfa gdzie działanie i sprzęgi programowania mogą ulec zmianie), „b1,b2,…,bN” (dla wydań beta, które tylko naprawiają błędy) i „pr1,pr2,…,prN” (dla końcowych testów wydań przed-wydaniem). Niektóre przykłady:

0.1.0

pierwsze, eksperymentalne wydanie pakietu

1.0.1a2

drugie wydanie alpha pierwszej łatki w wersji 1.0

classifiers must be specified in a list:

setup(...,
      classifiers=[
          'Development Status :: 4 - Beta',
          'Environment :: Console',
          'Environment :: Web Environment',
          'Intended Audience :: End Users/Desktop',
          'Intended Audience :: Developers',
          'Intended Audience :: System Administrators',
          'License :: OSI Approved :: Python Software Foundation License',
          'Operating System :: MacOS :: MacOS X',
          'Operating System :: Microsoft :: Windows',
          'Operating System :: POSIX',
          'Programming Language :: Python',
          'Topic :: Communications :: Email',
          'Topic :: Office/Business',
          'Topic :: Software Development :: Bug Tracking',
          ],
      )

Zmienione w wersji 3.7: setup now warns when classifiers, keywords or platforms fields are not specified as a list or a string.

2.9. Odpluskwianie skryptu instalacyjnego

Czasami sprawy źle idą, i skrypt instalacyjny nie robi tego czego chce twórca oprogramowania.

Distutils przechwytuje wszelkie wyjątki gdy uruchamiasz skrypt instalacyjny, i wypisuje prosty komunikat o błędzie zanim skrypt zostanie zakończony. Motywacją dla tego zachowania jest to aby nie wprowadzać zamieszania administratora który nie wie za wiele o języku pytonowskim i próbuje zainstalować pakiet. Jeśli dostanie długi duży wypis z głębi gardzieli Distutils, mogą pomyśleć że pakiet lub instalacja języka pytonowskiego jest popsuta gdyż nie przeczytali wszystkiego do dna i będą sądzić że jest to błąd dostępu.

On the other hand, this doesn’t help the developer to find the cause of the failure. For this purpose, the DISTUTILS_DEBUG environment variable can be set to anything except an empty string, and distutils will now print detailed information about what it is doing, dump the full traceback when an exception occurs, and print the whole command line when an external program (like a C compiler) fails.