Download Distribución de módulos Python

Document related concepts
no text concepts found
Transcript
Distribución de módulos Python
Greg Ward
8 de diciembre de 2000
E-mail: [email protected]
Resumen
Este documento describe las Herramientas de Distribución de Python (“Distutils”) desde el punto de vista del desarrollador 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.1 Un ejemplo simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2 Terminología general de Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.3 Terminología específica de Distutils . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
3
4
5
3
Escritura del guion de instalación
3.1 Enumeración de paquetes completos . . .
3.2 Enumeración de módulos individuales . .
3.3 Descripción de los módulos de extensión .
Nombre de extensiones y de paquetes . .
Ficheros fuente de extensión . . . . . . .
Opciones del preprocesador . . . . . . . .
Opciones de bibliotecas . . . . . . . . . .
5
6
6
7
7
8
8
9
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4
Escritura del fichero de configuración de la instalación
10
5
Creación de una distribución de fuentes
5.1 Especificación de los ficheros a distribuir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2 Opciones relativas al manifiesto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12
12
14
6
Creación de distribuciones binarias
6.1 Creación de distribuciones compiladas bobas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.2 Creación de paquetes RPM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.3 Creación de instaladores de Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
16
16
18
7
Ejemplos
7.1 Distribución Python pura (por módulo) .
7.2 Distribución Python pura (por paquete)
7.3 Módulo de extensión simple . . . . . .
7.4 Módulos de extensión múltiples . . . .
7.5 Todo junto . . . . . . . . . . . . . . . .
18
18
18
18
18
18
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
8
Extensión de las Distutils
8.1 Extensión de órdenes existentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.2 Implementación de nuevas órdenes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
18
18
9
Referencia
9.1 Compilación de módulos: la familia de órdenes build . . . . . . . .
build . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
build_py . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
build_ext . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
build_clib . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.2 Instalación de módulos: la familia de órdenes install . . . . . . .
install_lib . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
install_data . . . . . . . . . . . . . . . . . . . . . . . . . . . .
install_scripts . . . . . . . . . . . . . . . . . . . . . . . . .
9.3 Acciones de limpieza: la orden clean . . . . . . . . . . . . . . . . .
9.4 Creación de una distribución de fuentes: la orden sdist . . . . . . .
9.5 Creación de una distribución compilada: la familia de órdenes bdist
blib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
blib_dumb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
blib_rpm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
blib_wise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
18
18
18
18
18
18
18
18
18
19
19
19
19
19
19
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 usuarios/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:
• escribir un guion de instalación (‘setup.py’ por convención)
• (opcional) escribir un fichero de configuración de la instalación
• crear una distribución de código fuente
• (opcional) crear una o más distribuciones compiladas (binarias)
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.
2.1
Un ejemplo simple
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 informació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 contuviera 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’), desempaquetarlo y, desde el directorio ‘Foo-1.0’, ejecutar
python setup.py install
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.
2.1 Un ejemplo simple
3
órdenes de Distutils utilizan: la orden sdist es utilizada casi exclusivamente por desarrolladores de módulos, mientras
que la orden install es más común para los instaladores (aunque la mayoría de los desarrolladores querrán instalar
su propio código ocasionalmente).
Si deseas ponerles las cosas realmente fáciles a tus usuarios, puedes crear una o más distribuciones compiladas para
ellos. Por ejemplo, si estás funcionando en una máquina Windows y quieres facilitarles las cosas a otros usuarios de
Windows, puedes crear un instalador ejecutable (el tipo de distribución compilada más adecuado para esta plataforma)
con la orden bdist_wininst. Por ejemplo:
python setup.py bdist_wininst
creará un instalador ejecutable, ‘Foo-1.0.win32.exe’, en el directorio actual.
**no implementado aún** (Otro modo de crear instaladores ejecutables para Windows es con la orden
bdist_wise, que hace uso de Wise, el generador de instaladores que se utiliza en el propio Python, para generar el instalador. Los instaladores basados en Wise son más adecuados para aplicaciones de peso, que necesitan las
funciones de un instalador “de verdad”. bdist_wininst crea un fichero zip autoextraíble con una interfaz de usuario mínima, suficiente para colecciones de módulos pequeñas y medianas. Necesitarás tener instalada la versión XXX
de Wise en tu sistema para que la orden bdist_wise funcione. Está disponible en http://foo/bar/baz.)
En la actualidad (Distutils 0.9.2), el único formato de distribución compilado es el RPM, implementado por la orden
bdist_rpm. Por ejemplo, la siguiente orden creará un fichero RPM llamado ‘Foo-1.0.noarch.rpm’:
python setup.py bdist_rpm
(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
2.2 Terminología general de Python
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..
2.3
Terminología específica de Distutils
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 descargable y dirigida a ser instalada solidariamente. Como ejemplos de distribuciones de módulos ampliamente conocidas 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.
3
Escritura del guion de instalación
El guion de instalación es el centro de toda la actividad de la compilación, distribución e instalación de módulos
mediante las Distutils. El propósito principal del guion de instalación es el de describir la distribución de tu módulo a
las Distutils, para que las diversas órdenes que operan sobre tus módulos realicen el trabajo deseado. Según vimos en la
sección 2.1, el guion de instalación consta principalmente de una llamada a setup() y la mayoría de la información
proporcionada a las Distutils por el desarrollador del módulo se proporciona como argumentos clave a setup().
He aquí un ejemplo ligeramente más evolucionado, que seguiremos en las siguientes secciones: el propio guion de
instalación de las Distutils (recuerda que aunque las Distutils vienen incluidas en Python 1.6 y posteriores, existen
de manera independiente para que los usuarios de Python 1.5.2 puedan utilizarlas para instalar otras distribuciones de
módulos. El guion de instalación de las propias Distutils, que se muestra aquí, se utiliza para instalar el paquete en
Python 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 = "[email protected]",
url = "http://www.python.org/sigs/distutils-sig/",
packages = [’distutils’, ’distutils.command’],
)
Hay sólo dos diferencias entre este guion y el guion trivial para la distribución de un fichero presentado en la secció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.
2.3 Terminología específica de Distutils
5
Observa que los nombres del sistema de archivos (ficheros y directorios) del guion debe escribirse mediante la convención de Unix, es decir, separada por barras ‘/’. Las Distutils se ocuparán de convertir esta representación independiente
de la plataforma en la que sea apropiada para la plataforma de destino antes de usarla. Esto hace que tu guion de instalación sea transportable entre diferentes sistemas operativos, lo que es, por supuesto, una de las metas más importantes
de las Distutils. Siguiendo este objetivo, todos los nombres de subdirectorios se separan por barras (los programadores
de MacOS deberían tener en cuenta que la ausencia de barra inicial indica un camino relativo, la convención opuesta
a la usual en Mac, relativa a los dos puntos).
3.1
Enumeración de paquetes completos
La opción packages indica a las Distutils que procese (compile, distribuya, instale, etc.) todos los módulos en Python 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 proporcionar 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:
package_dir = {’’: ’lib’}
en tu guion de instalación (las claves de este diccionario son nombres de paquetes y un nombre vacío de paquete 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í:
package_dir = {’foo’: ’lib’}
Una entrada package: dir en el diccionario package_dir se aplica implícitamente a todos los paquetes bajo package, 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, aunque 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’).
3.2
Enumeración de módulos individuales
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:
py_modules = [’mod1’, ’pkg.mod2’]
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
6
3
Escritura del guion de instalación
que también existe ‘pkg/__init__.py’. Y de nuevo, puedes forzar la correspondencia entre paquetes y directorios usando
la opción package_dir.
3.3
Descripción de los módulos de extensión
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 enumerar 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.
Nombre de extensiones y de paquetes
El primer argumento del constructor de Extension siempre es el nombre de la extensión, nombres de paquetes
incluidos. Por ejemplo,
Extension("foo", ["src/foo1.c", "src/foo2.c"])
describe una extensión que reside en el paquete raíz, mientras
Extension("pkg.foo", ["src/foo1.c", "src/foo2.c"])
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,
3.3 Descripción de los módulos de extensión
7
setup(...
ext_package = "pkg",
ext_modules = [Extension("foo", ["foo.c"]),
Extension("subpkg.bar", ["bar.c"])]
)
compilará ‘foo.c’ a la extensión pkg.foo y ‘bar.c’ a pkg.subpkg.bar.
Ficheros fuente de extensión
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!**
Opciones del preprocesador
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:
Extension("foo", ["foo.c"], include_dirs=["include"])
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
Extension("foo", ["foo.c"], include_dirs=["/usr/include/X11"])
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:
8
3
Escritura del guion de instalación
from distutils.sysconfig import get_python_inc
incdir = os.path.join(get_python_inc(plat_specific=1), "Numerical")
setup(...,
Extension(..., include_dirs=[incdir]))
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’])
equivale a poner esto al principio de cada fichero fuente C:
#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 library_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.
3.3 Descripción de los módulos de extensión
9
**still undocumented: extra_objects, extra_compile_args, extra_link_args, export_symbols—none of which are
frequently needed, some of which might be completely unnecessary!**
4
Escritura del fichero de configuración de la instalación
A menudo, no es posible escribir cada cosa necesaria para construir una distribución a priori: puede que necesites
obtener información del usuario o de su sistema para proseguir. Siempre que tal información sea simple (una lista de
directorios en los que buscar cabeceras o bibliotecas de C, por ejemplo) resulta sencillo proporcionar un fichero de
configuración, ‘setup.cfg’, y dejar que lo edite el usuario. Los ficheros de configuración también permiten proporcionar
valores por omisión de cualquier opción de línea de órdenes que el usuario puede forzar mediante opciones en la línea
de órdenes o mediante la edición de dichos ficheros..
Si las necesidades son más avanzadas, como, por ejemplo, determinar qué extensiones se han de construir dependiendo
de las propiedades de la instalación del sistema, se necesita usar los servicios de “auto-configuración” de las Distutils.
Empezaron a aparecer en la versión 0.9, pero, en el momento en que se escribe esto, no son suficientemente estables o
maduras para su uso en entornos de producción.
**should reference description of distutils config files in “Installing” manual here**
El fichero de configuración de la instalación es un término medio entre el guion de instalación (que idealmente es
transparente para el instalador2 ) y la línea de órdenes del guion de instalación, que queda totalmente fuera de tu
control y al albedrío del instalador. De hecho, ‘setup.cfg’ (y otros ficheros de configuración de Distutils presentes en
el sistema final) se procesan tras el contenido del guion de instalación, pero antes de la línea de órdenes. Esto supone
varias consecuencias favorables:
• 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’
La sintaxis básica del fichero de configuración es simple:
[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
10
ideal no se logrará, probablemente, hasta que las Distutils den servicio de auto-configuración completo.
4
Escritura del fichero de configuración de la instalación
> python setup.py --help build_ext
[...]
Options for ’build_ext’ command:
--build-lib (-b)
directory for compiled extension modules
--build-temp (-t)
directory for temporary files (build by-products)
--inplace (-i)
ignore build-lib and put compiled extensions into the
source directory alongside your pure Python modules
--include-dirs (-I) list of directories to search for header files
--define (-D)
C preprocessor macros to define
--undef (-U)
C preprocessor macros to undefine
[...]
o consultando la sección 9 de este documento (la referencia de órdenes).
Observa que una opción que se escriba --pis-pas en la línea de órdenes se escribe pis_pas en los ficheros de configuración.
Supón, por ejemplo, que quieres que las extensiones se compilen “en el sitio”: Hay una extensión pkg.ext y quieres
que el fichero de la extensión compilada, ‘ext.so’ en Unix, se genere en el mismo directorio de fuentes que los módulos
de Python puro pkg.mod1 y pkg.mod2. Siempre puedes usar la opción --inplace de la línea de órdenes para
asegurarlo:
python setup.py build_ext --inplace
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 ficheros 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 <[email protected]>
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,
python setup.py sdist
(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:
python setup.py sdist --formats=gztar,zip
para generar un ‘.tar.gz’ y un ‘.zip’. Están disponibles los siguientes formatos:
Formato
zip
gztar
bztar
ztar
tar
Descripción
fichero zip (‘.zip’)
fichero tar/gzip (‘.tar.gz’)
fichero tar/bzip2 (‘.tar.gz’)
fichero tar comprimido (‘.tar.Z’)
tar file (‘.tar’)
Notas
(1),(3)
(2),(4)
(4)
(4)
(4)
Notas:
(1) predeterminado en Windows
(2) predeterminado en Unix
(3) requiere utilidad zip externa o modulo zipfile (no incluido en la biblioteca estándar de Python)
(4) requiere utilidades externas: tar y otra, como gzip, bzip2 o compress
5.1 Especificación de los ficheros a distribuir
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
12
5
Creación de una distribución de fuentes
‘MANIFEST’, que contiene la lista exacta de los ficheros a incluir en la distribución fuente. La orden sdist procesa
esta plantilla y genera un manifiesto basado en las instrucciones contenidas en ella y en lo que se encuentre en el
sistema de ficheros.
Si prefieres escribir tu propio fichero de manifiesto, el formato es bastante sencillo: un fichero por línea, sólo ficheros
normales (o enlaces simbólicos). Si proporcionas tu propio ‘MANIFEST’, hay que especificar todo: el juego predeterminado de ficheros anteriormente descrito no se aplica en este caso.
La plantilla del manifiesto tiene una orden por línea, donde cada orden especifica un conjunto de ficheros que incluir
o excluir de la distribución fuente. Por ejemplo, y retomando la propia plantilla de manifiesto de las Distutils:
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 configuració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’
5.1 Especificación de los ficheros a distribuir
13
9. en el árbol ‘examples’, incluir cualquier concordancia con ‘*.py’
10. eliminar todos los ficheros de los directorios que concuerden con ‘examples/sample?/build’—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 las las dos órdenes recursive-include
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.
5.2
Opciones relativas al manifiesto
El curso normal de operaciones de la orden sdist es la siguiente:
• si no existe el fichero de manifiesto, ‘MANIFEST’, leer ‘MANIFEST.in’ y crear ‘MANIFEST’
• si no existe ni ‘MANIFEST’ ni ‘MANIFEST.in’, crear un manifiesto con el conjunto predeterminado de ficheros3
• si ‘MANIFEST.in’ o el guion de configuración (‘setup.py’) son más recientes que ‘MANIFEST’, recrear
‘MANIFEST’ a partir de ‘MANIFEST.in’
• usar la lista actual de ficheros de ‘MANIFEST’ (recién generada o recuperada) para crear los archivos de distribución de fuentes
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:
python setup.py sdist --force-manifest
O puede que sólo se desee (re)generar el manifiesto, sin crear una distribución de fuentes:
python setup.py sdist --manifest-only
--manifest-only implica --force-manifest. -o es la abreviatura de --manifest-only y -f la de --force-manifest.
6
Creación de distribuciones binarias
Una “distribución compilada” se corresponde con los nombres comunes de “paquete binario” o “instalador” (dependiendo de tu bagaje cultural). No es necesario que sea binaria, sin embargo, porque es posible que sólo contenga código
fuente de Python o bytecode. No lo llamamos paquete porque la palabra ya estaba tomada para otra cosa en Python.
Instalador es un término específico de Windows. **do Mac people use it?**
Una distribución compilada es la manera de facilitar más las cosas a los instaladores de la distribución de módulos: para
los usuarios de Linux basado en RPM, es un RPM binario; para los usuarios de Windows, un instalador ejecutable; para
3 En las versiones de las Distutils hasta la 0.9.2 inclusive (Python 2.0b1), esta característica no funcionaba; se debe usar la opción -f (--forcemanifest) para superar el error.
14
6
Creación de distribuciones binarias
los usuarios de Debian, un paquete Debian, etc. Por supuesto, nadie será capaz de generar distribuciones para todas las
plataformas habidas y por haber, por lo que las Distutils están diseñadas para permitir que los diseñadores de módulos
se concentren en su especialidad, escribir código y generar las distribuciones de fuentes, mientras surge una especie
nueva, los empaquetadores, para convertir las distribuciones de fuentes en distribuciones para tantas plataformas como
sea posible.
Por supuesto, el desarrollador de módulos puede ser su propio empaquetador. Podría ser un voluntario “de por ahí”
que tuviera acceso a una plataforma a la que no tiene acceso el desarrollador original. Podría, incluso, ser software
que periódicamente recopilase las distribuciones de fuentes y las compilase de tantos modos como fuera posible.
Independientemente de la especie de la bestia en cuestión, un empaquetador usa el guion de configuración y la familia
de órdenes bdist para generar distribuciones compiladas.
Por ejemplo, si ejecuto la siguiente orden en el árbol de fuentes de las Distutils:
python setup.py bdist
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 predeterminado 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:
Formato
gztar
ztar
tar
zip
rpm
srpm
wininst
Descripción
fichero tar gzipeado (‘.tar.gz’)
fichero tar comprimido (‘.tar.Z’)
fichero tar (‘.tar’)
fichero zip (‘.zip’)
RPM
RPM de fuentes
fichero ZIP autoextraíble para Windows
Notas
(1),(3)
(3)
(3)
(4)
(5)
(5) **to do!**
(2),(6)
Notas:
(1) predeterminado en Unix
(2) predeterminado en Windows **to-do!**
4 el
fichero se considera “bobo” porque se debe desempaquetar en una ubicación específica para que funcione
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 directamente 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
bdist_dumb
bdist_rpm
bdist_wininst
Formatos
tar, ztar, gztar, zip
rpm, srpm
wininst
Las siguientes secciones proporcionan detalles de las diferentes órdenes bdist_*.
6.1
Creación de distribuciones compiladas bobas
**Need to document absolute vs. prefix-relative packages here, but first I have to implement it!**
6.2
Creación de paquetes RPM
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:
python setup.py bdist_rpm
o la orden bdist con la opción --format:
python setup.py bdist --formats=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:
python setup.py bdist_rpm --packager="Juana Pérez <[email protected]>" \
bdist_wininst --target_version="2.0"
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’:
16
6
Creación de distribuciones binarias
opción o sección del fichero ‘.spec’ de RPM
Name
Resumen (en el preámbulo)
Versión
Vendor
Copyright
Url
%description (section)
Opción del guion de configuración de Distutils
name
descripción
versión
author y author_email o
maintainer y maintainer_email
licence
url
long_description
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
Release
Group
Vendor
Packager
Provides
Requires
Conflicts
Obsoletes
Distribution
BuildRequires
Icon
opción bdist_rpm
release
group
vendor
packager
provides
requires
conflicts
obsoletes
distribution_name
build_requires
icon
valor predeterminado
“1”
“Development/Libraries”
(see above)
(none)
(none)
(none)
(none)
(none)
(none)
(none)
(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:
> python setup.py bdist_rpm --spec-only
# ...edit dist/FooBar-1.0.spec
> python setup.py bdist_rpm --spec-file=dist/FooBar-1.0.spec
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.
6.2 Creación de paquetes RPM
17
6.3
7
Creación de instaladores de Windows
Ejemplos
7.1
Distribución Python pura (por módulo)
7.2
Distribución Python pura (por paquete)
7.3
Módulo de extensión simple
7.4
Módulos de extensión múltiples
7.5
Todo junto
8
Extensión de las Distutils
8.1
Extensión de órdenes existentes
8.2
Implementación de nuevas órdenes
9
9.1
Referencia
Compilación de módulos: la familia de órdenes build
build
build_py
build_ext
build_clib
9.2
Instalación de módulos: la familia de órdenes install
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
Esta orden instala todos los guiones (de Python) de la distribución.
18
9
Referencia
9.3
Acciones de limpieza: la orden clean
9.4
Creación de una distribución de fuentes: la orden sdist
**fragment moved down from above: needs context!** Las órdenes de la plantilla del manifiesto son:
Command
include pat1 pat2 ...
exclude pat1 pat2 ...
recursive-include dir pat1 pat2 ...
recursive-exclude dir pat1 pat2 ...
global-include pat1 pat2 ...
global-exclude pat1 pat2 ...
prune dir
graft dir
Description
incluir todos los ficheros que concuerden
con cualquiera de los patrones indicados
excluir todos los ficheros que concuerden
con cualquiera
de los patrones indicados
incluir todos los ficheros contenidos en
dir que concuerden con cualquiera de
los patrones indicados
excluir todos los ficheros contenidos en
dir que concuerden con cualquiera de
los patrones indicados
incluir todos los ficheros de cualquier
parte del árbol de fuentes que concuerden
con cualquiera de los patrones indicados
excluir todos los ficheros de cualquier
parte del árbol de fuentes que concuerden
con cualquiera de los patrones indicados
excluir todos los ficheros contenidos en 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**
9.5
Creación de una distribución compilada: la familia de órdenes bdist
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
contener caracteres ASCII, sin acentos ni eñes.
9.3 Acciones de limpieza: la orden clean
19