Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Greg Ward
8 de diciembre de 2000
E-mail: gward@python.net
Resumen
Este documento describe las Herramientas de Distribución de Python (“Distutils”) desde el punto de vista del de-
sarrollador de módulos. Describe cómo utilizar las Distutils para hacer que los módulos y extensiones de Python
fácilmente accesibles a una amplia audiencia haciendo más automático el proceso de compilar/liberar/instalar.
Índice General
1 Introducción 2
2 Conceptos y terminología 2
2.1 Un ejemplo simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.2 Terminología general de Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.3 Terminología específica de Distutils . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
7 Ejemplos 18
7.1 Distribución Python pura (por módulo) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
7.2 Distribución Python pura (por paquete) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
7.3 Módulo de extensión simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
7.4 Módulos de extensión múltiples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
7.5 Todo junto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
8 Extensión de las Distutils 18
8.1 Extensión de órdenes existentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
8.2 Implementación de nuevas órdenes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
9 Referencia 18
9.1 Compilación de módulos: la familia de órdenes build . . . . . . . . . . . . . . . . . . . . . . . . . 18
build . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
build_py . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
build_ext . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
build_clib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
9.2 Instalación de módulos: la familia de órdenes install . . . . . . . . . . . . . . . . . . . . . . . . 18
install_lib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
install_data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
install_scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
9.3 Acciones de limpieza: la orden clean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
9.4 Creación de una distribución de fuentes: la orden sdist . . . . . . . . . . . . . . . . . . . . . . . . 19
9.5 Creación de una distribución compilada: la familia de órdenes bdist . . . . . . . . . . . . . . . . . 19
blib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
blib_dumb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
blib_rpm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
blib_wise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1 Introducción
Hasta ahora, los desarrolladores de módulos de Python no disponían de mucha infraestructura para la distribución de
módulos, ni los usuarios de Python de soporte para instalar y mantener módulos de terceras partes. Con la introducción
de las Herramientas de Distribución de Python (“Distutils” para abreviar) en Python 1.6, esta situación empezará a
mejorar.
Este documento sólo cubre el uso de Distutils para distribuir tus módulos de Python. El uso de Distutils no te ata
a Python 1.6 o superiores, sin embargo. Las Distutils funcionan perfectamente con Python 1.5.2 y es razonable (se
espera que común) que los usuarios de Python descarguen e instalen por separado las Distutils para poder instalar tus
módulos. Los usuarios de Python 1.6 (o superiores), por supuesto, no tendrán que añadir nada a su distribución de
Python para usar las Distutils en la instalación de módulos de terceros.
Este documento se concentra en el papel del desarrollador/distribuidor. Si buscas información sobre la instalación de
módulos de Python, deberías consultar el manual Instalación de módulos de Python.
2 Conceptos y terminología
El uso de las Distutils es bastante simple, tanto para los desarrolladores de módulos como para los usua-
rios/administradores que han de instalar módulos de terceros. Como desarrollador, tus responsabilidades (¡además
de escribir código fiable, bien documentado y probado, por supuesto!) son:
2 2 Conceptos y terminología
En este documento está cubierta cada una de estas tareas.
No todos los desarrolladores de módulos tienen acceso a varias plataformas, por lo que no siempre es factible esperar
que creen varias distribuciones binarias. Se espera que aparecerán intermediarios (los empaquetadores) para cubrir
esta necesidad. Los empaquetadores tomarán las distribuciones de código fuente liberadas por los desarrolladores de
módulos, las compilarán en una o varias plataformas y liberarán las distribuciones binarias resultantes. De este modo,
los usuarios de las plataformas más comunes serán capaces de instalar las distribuciones de módulos de Python más
extendidas del modo más natural en su plataforma, sin tener que ejecutar un solo guion ni compilar una línea de código.
El guion de instalación suele ser bastante simple, aunque, por estar escrito en Python, no hay límites arbitrarios sobre
lo que se puede hacer con él.1 Si sólo quieres distribuir un módulo denominado foo, contenido en un fichero ‘foo.py’,
tu guion de instalación puede reducirse a esto:
from distutils.core import setup
setup (name = "foo",
version = "1.0",
py_modules = ["foo"])
Observaciones:
• la mayoría de la información que se proporciona a las Distutils va en forma de argumentos clave a la función
setup()
• dichos argumentos pertenecen a dos categorías: meta-datos del paquete (nombre, número de versión) e informa-
ción sobre lo contenido en el paquete (una lista de módulos en Python puro, en este caso)
• los módulos se especifican por nombre de módulo, no nombre de fichero (esto se aplica también a los paquetes
y extensiones)
• se recomienda que proporciones más meta-datos, en particular tu nombre, dirección electrónica de correo y un
URL del proyecto (consulta la sección 3 si quieres ver un ejemplo)
Para crear una distribución de código fuente para este módulo, crearías un guion de instalación, ‘setup.py’, que contu-
viera el código anterior, y lo ejecutarías:
python setup.py sdist
lo que crearía un fichero comprimido (por ejemplo, un fichero tar de Unix, un zip en Windows) que contendría tu guion
de instalación, ‘setup.py’ y tu módulo, ‘foo.py’. El fichero se llamaría ‘Foo-1.0.tar.gz’ (o ‘.zip’) y se desempaquetaría
en un directorio ‘Foo-1.0’.
Si un usuario/a desea instalar tu módulo foo module, sólo tiene que descargar ‘Foo-1.0.tar.gz’ (o ‘.zip’), desempaque-
tarlo y, desde el directorio ‘Foo-1.0’, ejecutar
lo que finalmente copiaría ‘foo.py’ al directorio adecuado para módulos de terceros en su instalación de Python.
Este sencillo ejemplo muestra algunos conceptos fundamentales de las Distutils: Primero, tanto los desarrolladores
como los instaladores tienen la misma interfaz de usuario básica, el guion de instalación. La diferencia radica en qué
1 Pero modérate respecto a poner operaciones arbitrariamente costosas en el guion de instalación. Al contrario de los guiones del tipo de autoconf
[N. del T.: autoconf es la herramienta de GNU de configuración multiplataforma], es posible que el guion de instalación se ejecute varias veces en
el curso de la compilación e instalación de la distribución del módulo. Si es necesario que incluyas pasos potencialmente costosos en proceso dentro
de la cadena de Distutils, consulta la sección 8 sobre la extensión de las Distutils.
(utiliza la orden rpm, por lo que ha de ser ejecutado en un sistema basado en RPM, como Red Hat Linux, SuSE Linux
o Mandrake Linux).
Se puede consultar qué formatos de distribución están disponibles en cualquier momento ejecutando
python setup.py bdist --help-formats
Si estás leyendo este documento, es probable que tengas una idea clara de lo que son los módulos, extensiones, etc.
De cualquier manera, para estar seguro de que todos hablamos de lo mismo, damos el siguiente glosario de términos
comunes de Python:
módulo la unidad básica de reutilizabilidad de código en Python: un bloque de código importado por otro código.
Consideramos tres tipos de módulo: módulos Python puros, módulos de extensión y paquetes.
módulos Python puros escritos en Python y contenidos en un solo fichero ‘.py’ (y sus posibles ‘.pyc’ ‘.pyo’ files
asociados). Denominado a veces “módulo puro”.
módulo de extensión un módulo escrito en el lenguaje de bajo nivel de la implementación concreta: C/C++ en el caso
de CPython, Java en el de JPython. Contenido típicamente en un único fichero precompilado de carga dinámica,
es decir, un fichero objeto compartido (‘.so’) en Unix/CPython, una DLL (con la extensión cambiada a ‘.pyd’)
en el caso de Windows/CPython o un fichero de clase Java (‘.class’) en el caso de JPython (en la actualidad, las
Distutils solo gestionan extensiones en C/C++ para CPython).
paquete un módulo que contiene otros módulos. Suele estar contenido en un subdirectorio del sistema de ficheros y
se destaca por tener un fichero de nombre ‘__init__.py’.
paquete raíz la raíz de la jerarquía de paquetes. No es realmente un paquete, porque no tiene un fichero ‘__init__.py’,
pero había que bautizarlo. La inmensa mayoría de la biblioteca estándar reside en el paquete raíz. También
residen ahí muchos módulos pequeños de terceros que no pertenecen a una biblioteca mayor. Al contrario que
4 2 Conceptos y terminología
los paquetes normales, los módulos del paquete raíz pueden hallarse en muchos directorios, de hecho cada
directorio de sys.path puede contribuir módulos al paquete raíz..
Los siguientes términos son específicos de la distribución de módulos de Python mediante Distutils:
distribución de módulos una colección de módulos de Python distribuida conjuntamente como un recurso descarga-
ble y dirigida a ser instalada solidariamente. Como ejemplos de distribuciones de módulos ampliamente cono-
cidas se puede mencionar Numeric Python, PyXML, PIL (la Biblioteca de gestión de imágenes de Python) o
mxDateTime (se debería llamar a esto paquete, pero el término ya era utilizado en el contexto de Python y una
distribución de módulos puede tener cero, uno o varios paquetes Python.
distribución de módulos pura una distribución de módulos que sólo contiene módulos Python y paquete puros. A
veces se denomina “distribución pura”.
distribución de módulos no pura una distribución de módulos que contiene al menos un módulo de extensión. A
veces se denomina “distribución no pura”.
raíz de la distribución el directorio de nivel más alto de los ficheros de la distribución. Es el directorio en el que
reside ‘setup.py’ y desde el que hay que ejecutarlo.
Hay sólo dos diferencias entre este guion y el guion trivial para la distribución de un fichero presentado en la sec-
ción 2.1: más meta-datos y la especificación de módulos de Python puros por paquete, en lugar de por módulo. Esto
es relevante, ya que las Distutils poseen más de veinte módulos divididos en (hasta ahora) dos paquetes. Sería tedioso,
y difícil de mantener, generar una lista de módulos detallada.
La opción packages indica a las Distutils que procese (compile, distribuya, instale, etc.) todos los módulos en Pyt-
hon puros hallados en cada paquete mencionado en la lista packages. Para hacerlo, por supuesto, debe existir una
correspondencia entre los nombres de los paquetes y los directorios del sistema de ficheros. La correspondencia por
defecto es la evidente, es decir, el paquete distutils se encuentra en el directorio ‘distutils’ relativo a la raíz de la
distribución. De este modo, al decir packages = [’foo’] en tu guion de instalación, te comprometes a que las
Distutils encuentren un fichero ‘foo/__init__.py’ (posiblemente con diferente sintaxis en tu sistema, pero te la puedes
imaginar) relativo al directorio en el que reside tu guion de instalación (si no cumples tu compromiso, las Distutils
emitirán un aviso pero procesarán el paquete incorrecto de todos modos).
Si utilizas una convención diferente para ordenar tu directorio de fuentes, no hay problema: Sólo tienes que proporcio-
nar la opción package_dir para indicar a las Distutils tu convención. Por ejemplo, si mantienes todo el código fuente
en Python bajo ‘lib’, para que los módulos del “paquete raíz” (los que no están en ningún paquete) estén directamente
en ‘lib’, los módulos del paquete foo estén en ‘lib/foo’, y así sucesivamente, pondrías:
en tu guion de instalación (las claves de este diccionario son nombres de paquetes y un nombre vacío de paque-
te indica el paquete raíz). En tal caso, cuando digas packages = [’foo’], quieres decir que existe el fichero
‘lib/foo/__init__.py’.
Otra convención posible es poner el paquete foo justo en ‘lib’, el paquete foo.bar en ‘lib/bar’, etc. Esto se describiría
en el guion de instalación así:
Una entrada package: dir en el diccionario package_dir se aplica implícitamente a todos los paquetes bajo packa-
ge, por lo que el caso de foo.bar se gestiona de modo automáticamente. En este ejemplo, tener packages =
[f́oo’, f́oo.bar’] indica a las Distutils que busque ‘lib/__init__.py’ y ‘lib/bar/__init__.py’ (no olvides que, aun-
que package_dir se aplica recursivamente, se debe enumerar de manera explícita todos los paquetes de packages: las
Distutils no recorrerán tu árbol de directorios buscando un fichero ‘__init__.py’).
Para una distribución de módulos pequeña, puede que prefieras enumerar todos los módulos, en lugar de enumerar
paquetes (especialmente en el caso de un solo módulo que va en el “paquete raíz”). Este caso trivial se presentó en la
sección 2.1. He aquí un ejemplo más sustancioso:
Se describen dos módulos, uno de ellos en el “paquete raíz” y el otro en el paquete pkg. De nuevo, la disposición por
omisión de paquetes y directorios implica que se pueden encontrar estos dos módulos en ‘mod1.py’ y ‘pkg/mod2.py’, y
Igual que escribir módulos de extensión de Python es algo más complicado que escribir simples módulos de Python,
describírselos a las Distutils también resulta más complicado. A diferencia de los módulos puros, no basta con enu-
merar los paquetes y los módulos y esperar que las Distutils salgan y encuentren los ficheros adecuados. Hay que
especificar el nombre de la extensión, los ficheros fuente y los requisitos de compilación/enlace que pudiera haber
(directorios de “include”, bibliotecas de enlace. . . ).
Todo esto se hace mediante otro argumento clave a setup(), la opción extensions. extensions es simplemente una
lista de instancias de Extension, cada una de las cuales describe un módulo de extensión simple. Supón que tu
distribución incluye una sola extensión, llamada foo e implementada por ‘foo.c’. Si no se necesitan instrucciones
adicionales para el compilador/enlazador, es bastante simple describir esta extensión:
Extension("foo", ["foo.c"])
La clase Extension se puede importar de distutils.core, junto con setup(). Así, el guion de configuración
de una distribución de módulos que contiene sólo esta extensión y nada más, sería:
from distutils.core import setup, Extension
setup(name = "foo", version = "1.0",
ext_modules = [Extension("foo", ["foo.c"])])
La clase Extension (en realidad, la maquinaria subyacente de construcción de extensiones implementada por la
orden built_ext) proporciona mucha flexibilidad a la hora de describir extensiones de Python, tal como se describe
en las secciones posteriores.
El primer argumento del constructor de Extension siempre es el nombre de la extensión, nombres de paquetes
incluidos. Por ejemplo,
describe la misma extensión del paquete pkg. Los archivos fuente y el código objeto resultante son idénticos en ambos
casos. La única diferencia es dónde reside la extensión resultante (y, consecuentemente, su lugar dentro de la jerarquía
de espacios nominales de Python).
Si hay varias extensiones dentro del mismo paquete (o dentro del mismo paquete base), se debe usar el argumento
clave ext_package al llamar a la función setup(). Por ejemplo,
El segundo argumento del constructor de Extension es una lista de ficheros fuente. Como las Distutils sólo dan
soporte a extensiones en C/C++, suelen ser ficheros fuente C/C++. Asegúrate de usar las extensiones apropiadas para
distinguir los ficheros en C++: Parece que ‘.cc’ y ‘.cpp’ funcionan tanto en Unix como en Windows.
Sin embargo, también se puede incluir en la lista ficheros de interfaz SWIG (‘.i’). La orden build_ext gestiona
extensiones SWIG: Ejecutará SWIG sobre el fichero de interfaz y compilará el fichero C/C++ a la extensión.
**SWIG support is rough around edges and largely untested; especially SWIG support of C++ extensions!
Explain in more detail here when the interface firms up.**
Sobre algunas plataformas, es posible incluir ficheros no-fuente para que los procese el compilador y los incluya en la
extensión. En la actualidad, esto se aplica a los ficheros de recursos de Windows para Visual C++. **get more detail
on this feature from Thomas Heller!**
Hay tres argumentos opcionales de Extension que resultarán prácticos si hay que incluir directorios de búsqueda o
macros del preprocesador para definir/indefinir: include_dirs, define_macros y undef_macros.
Por ejemplo, si la extensión necesita ficheros de cabecera en el directorio ‘include’ de la raíz de la instalación, usa la
opción include_dirs:
Es posible especificar directorios absolutos. Si te consta que la extensión sólo se va a compilar en sistemas Unix con
X11R6 instalado en ‘/usr’, vale con poner
Se debe evitar este tipo de uso no-portable si esperar distribuir el código. Sería mejor incluir (p. ej.) <X11/Xlib.h>.
Si hay que incluir cabeceras de otra extensión de Python, puedes aprovecharte de que las Distutils instalan las cabeceras
de Python de manera consistente. Por ejemplo, las cabeceras de Numerical Python están instaladas (en una instalación
estándar de Unix) en ‘/usr/local/include/python1.5/Numerical’ (la ubicación exacta dependerá de la plataforma y de la
instalación de Python). Como el directorio de cabeceras C de Python —‘/usr/local/include/python1.5’ en este caso—
siempre está incluido en el camino de búsqueda al compilar extensiones de Python, lo mejor es incluir (para este
ejemplo) <Numerical/arrayobject.h>. Si te empeñas en poner el directorio ‘Numerical’ en tu camino de
búsqueda de cabeceras, puedes encontrar el directorio usando el módulo sysconfig de las Distutils:
Aunque esto resulte bastante portable (funcionará en cualquier instalación de de Python, independientemente de la
plataforma) es probable que resulte más sencillo escribir el código C de una manera más coherente.
Se pueden definir e indefinir macros del preprocesador con las opciones define_macros y undef_macros.
define_macros toma una lista de tuplas (name, value), donde name es el nombre de la macro para definir
(una cadena) y value es su valor: una cadena o None. Definir una macro FOO a None equivale a una línea #define
FOO el el fuente C. La mayoría de los compiladores pondrán FOO al valor cadena 1.) undef_macros es una lista
de macros a indefinir.
Por ejemplo:
Extension(...,
define_macros=[(’NDEBUG’, ’1’)],
(’HAVE_STRFTIME’, None),
undef_macros=[’HAVE_FOO’, ’HAVE_BAR’])
#define NDEBUG 1
#define HAVE_STRFTIME
#undef HAVE_FOO
#undef HAVE_BAR
Opciones de bibliotecas
También se pueden especificar las bibliotecas de enlace y los directorios en los que buscar dichas bibliotecas. La
opción libraries es una lista de bibliotecas de enlace, library_dirs es una lista de directorios en los que
buscar bibliotecas en el momento de enlazar y runtime_library_dirs es una lista de directorios en los que
buscar bibliotecas compartidas (DLLs, en Windows) en tiempo de ejecución.
Por ejemplo, si hay que enlazar bibliotecas que se sabe que están en el camino de búsqueda de bibliotecas estándar en
los sistemas de destino:
Extension(...,
libraries=["gdbm", "readline"])
Si es necesario enlazar con bibliotecas de una ubicación no estándar, habrá que incluir la ubicación en li-
brary_dirs:
Extension(...,
library_dirs=["/usr/X11R6/lib"],
libraries=["X11", "Xt"])
Como se ha indicado, se debe evitar este tipo de construcción no portable si tienes intención de distribuir código.
• los instaladores pueden forzar cosas que pongas en ‘setup.py’ editando ‘setup.cfg’
• Puedes proporcionar valores por omisión no estándar para las opciones que no sean fáciles de incluir en
‘setup.py’
• los instaladores pueden forzar cualquier cosa de ‘setup.cfg’ usando las opciones de línea de órdenes de ‘setup.py’
[orden]
opción=valor
...
donde orden es una de las órdenes de Distutils (por ejemplo, build_py o install) y opción es una de las opciones
válidas para dicha orden. En el fichero se puede proporcionar cualquier número de opciones para cada orden y se
puede incluir cualquier número de secciones de orden. Se pasan por alto las líneas en blanco y los comentarios (desde
el carácter # hasta el fin de la línea). Se puede dividir los valores de opciones largos sangrando las líneas posteriores a
la primera.
Se puede obtener la lista de opciones válidas para una orden particular con la opción universal --help (ayuda), por
ejemplo:
2 Este ideal no se logrará, probablemente, hasta que las Distutils den servicio de auto-configuración completo.
Pero esto exige que se especifique siempre la orden build_ext y recordar proporcionar --inplace. Es más sencillo
“ajustar y olvidar” esta opción incluyéndola en ‘setup.cfg’, el fichero de configuración de esta distribución:
[build_ext]
inplace=1
Esto afectará a todas las compilaciones de esta distribución de módulos, tanto si especificas build_ext como si
no. Si incluyes ‘setup.cfg’ en la distribución de fuentes, también afectará a las compilaciones del usuario final, lo
que puede no resultar adecuado para esta opción, ya que compilar siempre “en el sitio” las extensiones dañaría la
instalación de distribución de módulos. En ciertos casos concretos, sin embargo, se construyen en su mismo directorio
de instalación, así que es una posibilidad que puede resultar útil (distribuir extensiones que se han de compilar en el
directorio de instalación casi siempre es inconveniente, sin embargo).
Otro ejemplo: ciertas órdenes requieren muchas opciones que no cambian de una ejecución a la siguiente, por ejemplo,
bdist_rpm requiere todo lo necesario para generar un fichero ‘spec’ para generar una distribución RPM. Parte de
esta información viene del guion de instalación y parte es generada automáticamente por las Distutils (la lista de fiche-
ros instalados, por ejemplo). Sin embargo, otra parte debe ser proporcionada en forma de opciones de bdist_rpm,
tediosas de repetir en la línea de órdenes para cada ejecución. Por ello, he aquí un fragmento del propio ‘setup.cfg’ de
las Distutils:
[bdist_rpm]
release = 1
packager = Greg Ward <gward@python.net>
doc_files = CHANGES.txt
README.txt
USAGE.txt
doc/
examples/
Observa que la opción doc_files es simplemente una ristra de cadenas separadas por blancos, dividida en múltiples
líneas para favorecer la legibilidad.
11
5 Creación de una distribución de fuentes
Como se muestra en la sección 2.1, se usa la orden sdist para crear una distribución de fuentes. En el caso más
sencillo,
(suponiendo que no se ha especificado ninguna de las opciones sdist el en guion de configuración o en el fichero
de configuración), sdist genera el archivo comprimido con el formato más usual de la plataforma en cuestión. El
formato por omisión es concatenado con tar y comprimido con gzip (‘.tar.gz’) en Unix y fichero ZIP en Windows.
**no Mac OS support here** > Es posible especificar cuantos formatos sean necesarios usando la opción --formats,
por ejemplo:
Notas:
Si no se proporciona una lista explícita de ficheros (o instrucciones de cómo generarla), la orden sdist incluye un
conjunto mínimo en la distribución de fuentes:
• todos los ficheros fuentes Python implicados por py_modules y opciones packages
• todos los ficheros fuente C mencionados en ext_modules u opciones libraries (**getting C library sources
currently broken – no get_source_files() method in build_clib.py!**)
• cualquier cosa con pinta de guion de pruebas: ‘test/test*.py’ (en la actualidad, las Distutils no hacen nada con
los guiones de pruebas salvo incluirlos en las distribuciones de fuentes, pero en el futuro existirá una norma para
la comprobación de las distribuciones de módulos de Python)
• ‘README.txt’, léame, (o ‘README’), ‘setup.py’ (o como llamases a tu guion de configuración) y ‘setup.cfg’
Esto puede valer en algunos casos, pero es común que haya que especificar más ficheros para distribuir. El modo típico
de hacerlo es escribir una plantilla del manifiesto, denominada ‘MANIFEST.in’ de forma predeterminada. La plantilla
del manifiesto tiene simplemente una lista de instrucciones de cómo generar el fichero de manifiesto, denominado
include *.txt
recursive-include examples *.txt *.py
prune examples/sample?/build
El significado debería resultar claro: incluir todos los ficheros de la raíz de la distribución que concuerden con *.txt,
todos los ficheros bajo ‘examples’ que concuerden con *.txt o *.py, y excluir todos los ficheros que concuerden
con examples/sample?/build. Todo ello se realiza tras el conjunto de inclusión estándar, por lo que se puede
excluir ficheros del conjunto estándar con instrucciones explícitas en la plantilla del manifiesto (o se puede usar la
opción --no-defaults para desactivar el conjunto estándar por completo). Hay varias órdenes más en el mini-lenguaje
de la plantilla del manifiesto. Consulta la sección 9.4.
El orden de las órdenes en la plantilla del manifiesto es relevante: inicialmente, tenemos la lista inicial predeterminada
descrita anteriormente y cada orden va retirando o agregando ficheros de la lista. Una vez se ha procesado por completo
la plantilla del manifiesto, eliminamos los ficheros que no deberían incluirse en la distribución de fuentes:
• todos los ficheros del árbol de compilación de Distutils (por omisión ‘build/’)
• todos los ficheros de directorios llamados ‘RCS’ o ‘CVS’
Ahora tenemos nuestra lista completa de ficheros, que se escribe en el manifiesto para futura referencia y se usa para
construir el/los archivo/s final/es de la distribución.
Se puede desactivar el conjunto predeterminado de ficheros incluidos con la opción --no-defaults y desactivar la lista
estándar de exclusiones con la opción --no-prune.
Siguiendo el propio fichero de manifiesto de las Distutils, vamos a trazar cómo construye la orden sdist la lista de
ficheros que se incluyen en la distribución de fuentes de las Distutils:
1. incluir todos los ficheros fuente de Python de los subdirectorios ‘distutils’ y ‘distutils/command’ (porque los
paquetes correspondientes a esos dos directorios fueron mencionados en la opción packages del guion de con-
figuración, según lo contenido en la sección 3)
2. incluir ‘README.txt’, ‘setup.py’ y ‘setup.cfg’ (ficheros estándar)
3. incluir ‘test/test*.py’ (ficheros estándar)
4. incluir ‘*.txt’ de la raíz de la distribución (se volverá a encontrar ‘README.txt’ de nuevo, pero luego se desbrozan
tales redundancias)
5. incluir cualquier cosa que concuerde con ‘*.txt’ o ‘*.py’ del subdirectorio‘examples’ y los interiores a éste,
6. excluir todos los ficheros de los subdirectorios que concuerden con ‘examples/sample?/build’ y los interiores a
ellos—esto podría excluir ficheros incluidos por los dos pasos anteriores, por lo que es importante que la orden
prune de la plantilla del manifiesto venga tras la orden recursive-include
7. excluir el árbol ‘build’ por completo y cualquier directorio ‘RCS’ o ‘CVS’
8. en el árbol ‘examples’, incluir cualquier concordancia con ‘*.txt’
Al igual que en el guion de configuración, los nombres de ficheros y directorios de la plantilla del manifiesto deberían
separarse por barras ‘/’siempre. Las Distutils se ocuparán de convertir las barras en la representación estándar de la
plataforma de destino. De este modo, la plantilla del manifiesto es transportable entre diferentes sistemas operativos.
Hay un par de opciones que modifican este comportamiento. Se puede usar --no-defaults y --no-prune para desactivar
los conjuntos estándar de inclusión y exclusión. Observa que si no hay plantilla de manifiesto ni manifiesto y se usa
--no-defaults, se obtiene un manifiesto vacío. Otro error de Distutils 0.9.2 y anteriores causa una excepción fatal en
tal caso. Evitarlo es fácil: no reproduzcas el caso descrito.
Además, es posible forzar la regeneración del manifiesto, por ejemplo, si se han añadido o eliminado ficheros o
directorios que concuerdan con un patrón existente en el manifiesto, se debería regenerar el manifiesto:
O puede que sólo se desee (re)generar el manifiesto, sin crear una distribución de fuentes:
las Distutils generan mi distribución de módulos (en este caso, las propias Distutils ), generan un instalación “falsa”
(también en el directorio ‘build’) y crea el tipo de distribución predeterminada de la plataforma. El formato predeter-
minado para las distribuciones compiladas es un fichero tar “bobo”4 en Unix y un sencillo instalador ejecutable en
Windows.
Por lo tanto, la orden anterior, en un sistema Unix, genera ‘Distutils-0.9.1.plat.tar.gz’; descomprimiendo el tar en el sitio
correcto se instalan las Distutils, tal y como si se hubiera descargado la distribución de fuentes y se hubiera ejecutado
python setup.py install. El sitio correcto es la raíz del sistema de archivos o el directorio prefix de Python,
dependiendo de las opciones pasadas a la orden bdist_dumb; por omisión se generan distribuciones bobas relativas
a prefix .
Por supuesto, en el caso de las distribuciones de Python puras, esto no supone una ventaja sustancial, pero para
las distribuciones no puras, puede suponer el salto entre que alguien sea capaz de usar tus extensiones o no lo sea. Y
generar distribuciones compiladas “listas”, como los paquetes RPM o los instaladores ejecutables de Windows, facilita
enormemente las cosas incluso si la distribución no incluye extensiones.
La orden bdist tiene una opción --formats, parecida a la orden sdist, que se puede usar para elegir los tipos de
distribución compilada a generar: por ejemplo,
python setup.py bdist --format=zip
crearía, en un sistema Unix ‘Distutils-0.8.plat.zip’. Esto, nuevamente, se debería descomprimir en el sitio adecuado
para instalar las Distutils.
Los formatos disponibles para distribuciones compiladas son:
Notas:
15
(3) requiere utilidades externas: tar y gzip, bzip2 o compress
(4) requiere utilidad zip o el módulo zipfile (que no es parte de la biblioteca estándar de Python)
(5) requiere utilidad externa rpm, versión 3.0.4 o superior (usa rpm -version para averiguar qué versión tienes)
(6) **requisitos de bdist_wininst?**
No es necesario usar la orden bdist con la opción --formats, también se puede usar la orden que implementa direc-
tamente el formato deseado. Algunos de estas “sub-órdenes” bdist generan varios formatos similares; por ejemplo,
la orden bdist_dumb genera todos los formatos de archivo “bobos” (tar, ztar, gztar y zip) y bdist_rpm
genera los RPMs binarios y de fuentes. Las sub-órdenes bdist y los formatos que genera cada una son:
Orden Formatos
bdist_dumb tar, ztar, gztar, zip
bdist_rpm rpm, srpm
bdist_wininst wininst
**Need to document absolute vs. prefix-relative packages here, but first I have to implement it!**
El formato RPM es estándar en muchas distribuciones de Linux populares, incluyendo Red Hat, SuSE y Mandrake.
Si tu entorno habitual se basa en RPM, es trivial crear paquetes RPM para otros usuarios de la misma distribución.
Dependiendo de la complejidad de la distribución de módulos y de las diferencias entre distribuciones de Linux, puede
que seas capaz de crear RPMs para otras distribuciones basadas en RPM.
El modo usual de crear un RPM de tu distribución de módulos es ejecutar bdist_rpm:
La primera permite especificar opciones específicas de RPM, la segunda permite especificar más de un formato en una
sola ejecución. Si necesitas las dos cosas, puedes especificar múltiples órdenes bdist_* y sus opciones:
La creación de paquetes RPM va dirigida por un fichero ‘.spec’, del mismo modo en que el guion de configuración
dirige las Distutils. Para facilitar la vida en la medida de lo posible, la orden bdist_rpm crea normalmente un fichero
‘.spec’ basado en la información proporcionada en el guion de configuración, la línea de órdenes o cualquier fichero
de configuración de Distutils. Del guion de configuración se derivan varias opciones y secciones del fichero ‘.spec’:
Además hay tres opciones más en los ficheros ‘.spec’ sin correspondencia en las opciones del guion de configuración.
La mayoría de ellas se gestionan mediante opciones de la orden bdist_rpm:
opción o sección del fichero ‘.spec’ de RPM opción bdist_rpm valor predeterminado
Release release “1”
Group group “Development/Libraries”
Vendor vendor (see above)
Packager packager (none)
Provides provides (none)
Requires requires (none)
Conflicts conflicts (none)
Obsoletes obsoletes (none)
Distribution distribution_name (none)
BuildRequires build_requires (none)
Icon icon (none)
Obviamente, proporcionar estas opciones en la línea de órdenes sería tedioso y propenso a errores, por lo que resulta
mejor ponerlas en el fichero de configuración de la instalación, ‘setup.cfg’, consultar la sección 4. Si distribuyes
o empaquetas muchas distribuciones de módulos de Python, es posible que te convenga poner las opciones que se
apliquen a todas ellas en tu fichero personal de configuración de Distutils (‘~/.pydistutils.cfg’).
Hay tres pasos para generar un paquete binario RPM y todos ellos los gestiona Distutils automáticamente:
1. crear un fichero ‘.spec’, que describe el paquete (análogo al guion de configuración de Distutils; mucha de la
información de este fichero acaba en ‘.spec’)
2. crear el RPM fuente
3. crear el RPM “binario” (que puede contener, o no, código binario, dependiendo de si tu distribución de módulos
contiene extensiones de Python)
RPM suele juntar los dos últimos pasos. Al usar Distutils, se suelen juntar los tres.
Si lo deseas, puedes separar estos tres pasos. Puedes usar la opción --spec-only para hacer que bdist_rpm sólo cree
el fichero ‘.spec’ y termine. En este caso, el fichero ‘.spec’ quedará en el “directorio de distribución”, normalmente
‘dist/’, pero se puede personalizar mediante la opción --dist-dir. Normalmente, bdist_rpm deja el fichero ‘.spec’
en un directorio temporal bastante profundo
**this isn’t implemented yet—is it needed?!** También se puede especificar un fichero ‘.spec’ a medida con la
opción --spec-file. Utilizada junto con --spec-only, permite personalizar el fichero ‘.spec’ manualmente:
Puede que sea mejor sobreescribir la orden bdist_rpm estándar con una que escriba exactamente lo deseado en el
fichero ‘.spec’ Consulta la sección 8 para obtener información sobre la extensión de las Distutils.
7 Ejemplos
9 Referencia
build
build_py
build_ext
build_clib
La orden install asegura que las órdenes de compilación se han ejecutado y a continuación ejecuta las sub-órdenes
install_lib, install_data y install_scripts.
install_lib
install_data
Esta orden instala todos los ficheros de datos proporcionados con la distribución.
install_scripts
18 9 Referencia
9.3 Acciones de limpieza: la orden clean
**fragment moved down from above: needs context!** Las órdenes de la plantilla del manifiesto son:
Command Description
include pat1 pat2 ... incluir todos los ficheros que concuerden
con cualquiera de los patrones indicados
exclude pat1 pat2 ... excluir todos los ficheros que concuerden
con cualquiera
de los patrones indicados
recursive-include dir pat1 pat2 ... incluir todos los ficheros contenidos en
dir que concuerden con cualquiera de
los patrones indicados
recursive-exclude dir pat1 pat2 ... excluir todos los ficheros contenidos en
dir que concuerden con cualquiera de
los patrones indicados
global-include pat1 pat2 ... incluir todos los ficheros de cualquier
parte del árbol de fuentes que concuerden
con cualquiera de los patrones indicados
global-exclude pat1 pat2 ... excluir todos los ficheros de cualquier
parte del árbol de fuentes que concuerden
con cualquiera de los patrones indicados
prune dir excluir todos los ficheros contenidos en dir
graft dir incluir todos los ficheros contenidos en dir
Los patrones son del estilo de “glob” de Unix: * concuerda con cualquier secuencia de caracteres de nombre de fichero
normales, ? concuerda con un solo carácter normal de nombre de fichero y [rango] concuerda con cualquiera de los
caracteres de rango (por ejemplo, a-z, a-zA-Z, a-f0-9_.)5 . La definición de “carácter normal de nombre de
fichero” depende de la plataforma: En Unix es cualquier cosa excepto la barra. En Windows, cualquier cosa excepto la
barra o los dos puntos. En Mac, cualquier cosa excepto los dos puntos. **Windows and Mac OS support not there
yet**
blib
blib_dumb
blib_rpm
blib_wise
5 N. del T.: Lo de las eñes y acentos es un asunto aparte. Mi opinión personal es que los nombres de ficheros para distribución sólo deberían