Incluyendo archivos que no son de Python con setup.py

¿Cómo hago para que setup.py incluya un archivo que no sea parte del código? (Específicamente, es un archivo de licencia, pero podría ser cualquier otra cosa).

Quiero poder controlar la ubicación del archivo. En la carpeta de origen original, el archivo está en la raíz del paquete. (es decir, en el mismo nivel que el __init__.py superior). Quiero que permanezca exactamente allí cuando se instala el paquete, independientemente del sistema operativo. ¿Cómo puedo hacer eso?

Probablemente la mejor manera de hacerlo es usar la directiva setuptools . Esto significa usar setuptools (o distribute ) en lugar de distutils , pero esta es una “actualización” muy fluida.

Aquí hay un ejemplo completo (pero no probado):

 from setuptools import setup, find_packages setup( name='your_project_name', version='0.1', description='A description.', packages=find_packages(exclude=['ez_setup', 'tests', 'tests.*']), package_data={'': ['license.txt']}, include_package_data=True, install_requires=[], ) 

Tenga en cuenta las líneas específicas que son críticas aquí:

 package_data={'': ['license.txt']}, include_package_data=True, 

package_data es un dict de nombres de paquetes (vacío = todos los paquetes) a una lista de patrones (puede incluir globos). Por ejemplo, si solo desea especificar archivos dentro de su paquete, también puede hacerlo:

 package_data={'yourpackage': ['*.txt', 'path/to/resources/*.txt']} 

La solución aquí definitivamente es no cambiar el nombre de los archivos que no son py con una extensión .py .

Vea la presentación de Ian Bicking para más información.

ACTUALIZACIÓN: Otro enfoque [Mejor]

Otro enfoque que funciona bien si solo desea controlar el contenido de la distribución de origen ( sdist ) y tener archivos fuera del paquete (por ejemplo, el directorio de nivel superior) es agregar un archivo MANIFEST.in . Consulte la documentación de Python para el formato de este archivo.

Desde que escribí esta respuesta, descubrí que el uso de MANIFEST.in suele ser un enfoque menos frustrante para asegurarse de que su distribución de origen ( tar.gz ) tenga los archivos que necesita.

Por ejemplo, si desea incluir los requirements.txt desde el nivel superior, incluya recursivamente el directorio de “datos” de nivel superior:

 include requirements.txt recursive-include data * 

Sin embargo, para que estos archivos se copien en el momento de la instalación en la carpeta del paquete dentro de los paquetes del sitio, deberá proporcionar include_package_data=True para la función setup() . Consulte Agregar archivos que no son de código para obtener más información.

Para lograr lo que estás describiendo tomará dos pasos …

  • El archivo necesita ser agregado al archivo fuente.
  • setup.py necesita ser modificado para instalar el archivo de datos en la ruta de origen

Paso 1: para agregar el archivo al archivo fuente, inclúyalo en el MANIFEST

Cree una plantilla MANIFEST en la carpeta que contiene setup.py

El MANIFEST es básicamente un archivo de texto con una lista de todos los archivos que se incluirán en el archivo fuente.

Así es como se ve el MANIFIESTO para mi proyecto:

  • CHANGELOG.txt
  • INSTALL.txt
  • LICENCIA.txt
  • pypreprocessor.py
  • README.txt
  • setup.py
  • test.py
  • TODO.txt

Nota: aunque sdist agrega algunos archivos automáticamente , prefiero especificarlos explícitamente para estar seguro en lugar de predecir lo que hace y lo que no.

Paso 2: para instalar el archivo de datos en la carpeta de origen, modifique setup.py

Dado que está buscando agregar un archivo de datos (LICENSE.txt) a la carpeta de instalación de origen, debe modificar la ruta de instalación de datos para que coincida con la ruta de instalación de origen. Esto es necesario porque, de forma predeterminada, los archivos de datos se instalan en una ubicación diferente a los archivos de origen.

Para modificar el directorio de instalación de datos para que coincida con el directorio de instalación de origen …

Tire de la información del directorio de instalación de distutils con:

 from distutils.command.install import INSTALL_SCHEMES 

Modifique el directorio de instalación de datos para que coincida con el directorio de instalación de origen:

 for scheme in INSTALL_SCHEMES.values(): scheme['data'] = scheme['purelib'] 

Y, agregue el archivo de datos y la ubicación a la configuración ():

 data_files=[('', ['LICENSE.txt'])] 

Nota: Los pasos anteriores deben cumplir exactamente lo que describió de manera estándar sin requerir bibliotecas de extensión.

cree MANIFEST.in en la raíz del proyecto con recursive-include al directorio requerido o con el nombre del archivo.

 include LICENSE include README.rst recursive-include package/static * recursive-include package/templates * 

la documentación se puede encontrar aquí

En setup.py bajo setup (:

 setup( name = 'foo library' ... package_data={ 'foolibrary.folderA': ['*'], # All files from folder A 'foolibrary.folderB': ['*.txt'] #All text files from folder B }, 

Aquí hay una respuesta más simple que me funcionó.

Primero, según el comentario de un desarrollador de Python anterior, no se requieren herramientas de configuración:

 package_data is also available to pure distutils setup scripts since 2.3. – Éric Araujo 

Eso es genial porque poner un requisito de setuptools en tu paquete significa que también tendrás que instalarlo. En breve:

 from distutils.core import setup setup( # ...snip... packages = ['pkgname'], package_data = {'pkgname': ['license.txt']}, ) 

Paso 1: cree un archivo MANIFEST.in en la misma carpeta con setup.py

Paso 2: incluya la ruta relativa a los archivos que desea agregar en MANIFEST.in

 include README.rst include docs/*.txt include funniest/data.json 

Paso 3: establezca include_package_data=True en la función setup() para copiar estos archivos al sitio-paquete

la referencia está aquí

Solo quería hacer un seguimiento de algo que encontré trabajando con Python 2.7 en Centos 6. Agregar los datos_paquetes o datos_archivos como se mencionó anteriormente no me funcionó. Agregué un MANIFEST.IN con los archivos que quería, que colocaron los archivos que no son de python en el archivo, pero no los instalé en la máquina de destino a través de RPM.

Al final, pude obtener los archivos en mi solución usando las “opciones” en la configuración / herramientas de configuración. Los archivos de opciones le permiten modificar varias secciones del archivo de especificaciones desde setup.py. Como sigue.

 from setuptools import setup setup( name='theProjectName', version='1', packages=['thePackage'], url='', license='', author='me', author_email='me@email.com', description='', options={'bdist_rpm': {'install_script': 'filewithinstallcommands'}}, ) 

archivo – MANIFEST.in:

 include license.txt 

archivo – archivo con comandos de instalación:

 mkdir -p $RPM_BUILD_ROOT/pathtoinstall/ #this line installs your python files python setup.py install -O1 --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES #install license.txt into /pathtoinstall folder install -m 700 license.txt $RPM_BUILD_ROOT/pathtoinstall/ echo /pathtoinstall/license.txt >> INSTALLED_FILES 

Quería publicar un comentario en una de las preguntas, pero no tengo suficiente reputación para hacerlo>.>

Esto es lo que funcionó para mí (se me ocurrió después de remitir los documentos):

 package_data={ 'mypkg': ['../*.txt'] }, include_package_data: False 

La última línea fue, por extraño que parezca, también crucial para mí (también puede omitir este argumento de palabras clave, funciona igual).

Lo que hace es copiar todos los archivos de texto en su directorio de nivel superior o raíz (un nivel por encima del paquete mypkg que desea distribuir).

¡Espero que esto ayude!

Descubrí una solución alternativa: lgpl2.1_license.txt nombre de lgpl2.1_license.txt a lgpl2.1_license.txt.py y coloqué algunas comillas triples alrededor del texto. Ahora no necesito usar la opción data_files ni especificar ninguna data_files absoluta. Hacer que sea un módulo de Python es feo, lo sé, pero lo considero menos feo que especificar rutas absolutas.