python3 - Incluyendo archivos que no son de Python con setup.py
install python3 distutils (7)
Aquí hay una respuesta más simple que funcionó para mí.
Primero, según el comentario anterior de un Python Dev, no se requiere setuptools:
package_data is also available to pure distutils setup scripts
since 2.3. – Éric Araujo
Eso es genial porque poner un requisito de herramientas de configuración en su paquete significa que tendrá que instalarlo también. En breve:
from distutils.core import setup
setup(
# ...snip...
packages = [''pkgname''],
package_data = {''pkgname'': [''license.txt'']},
)
¿Cómo hago que setup.py
incluya un archivo que no es 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 fuente original, el archivo está en la raíz del paquete. (es decir, en el mismo nivel que __init__.py
más __init__.py
). Quiero que permanezca exactamente allí cuando se instala el paquete, independientemente del sistema operativo. ¿Cómo puedo hacer eso?
En setup.py en configuración (:
setup(
name = ''foo library''
...
package_data={
''foolibrary.folderA'': [''*''], # All files from folder A
''foolibrary.folderB'': [''*.txt''] #All text files from folder B
},
Encontré una solución: lgpl2.1_license.txt
mi lgpl2.1_license.txt
a lgpl2.1_license.txt.py
y puse algunas comillas triples alrededor del texto. Ahora no necesito usar la opción data_files
ni especificar ninguna data_files
absoluta. Convertirlo en un módulo de Python es feo, lo sé, pero lo considero menos feo que especificar rutas absolutas.
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 (empty = all packages) a una lista de patrones (puede incluir globs). Por ejemplo, si solo desea especificar archivos dentro de su paquete, puede hacerlo también:
package_data={''yourpackage'': [''*.txt'', ''path/to/resources/*.txt'']}
La solución aquí es definitivamente no cambiar el nombre de sus archivos no 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 tiene archivos fuera del paquete (por ejemplo, el directorio de nivel superior) es agregar un archivo MANIFEST.in
. Consulte la documentación de Python para conocer el formato de este archivo.
Desde que escribí esta respuesta, descubrí que usar MANIFEST.in
suele ser un enfoque menos frustrante para asegurarse de que la distribución de origen ( tar.gz
) tenga los archivos que necesita.
Por ejemplo, si desea incluir los requirements.txt
del nivel superior, recursivamente incluya 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 site-packages, deberá suministrar include_package_data=True
a la función setup()
. Consulte Agregar archivos sin código para obtener más información.
Solo quería hacer un seguimiento de algo que encontré trabajando con Python 2.7 en Centos 6. Agregar el package_data o data_files como se mencionó anteriormente no funcionó para mí. Agregué un MANIFEST.IN con los archivos que quería, que ponían los archivos que no eran de Python en el tarball, pero no los instalaba en el equipo de destino a través de RPM.
Al final, pude obtener los archivos en mi solución usando las "opciones" en las herramientas de configuración / configuración. Los archivos de opciones le permiten modificar varias secciones del archivo de especificaciones de setup.py. Como sigue.
from setuptools import setup
setup(
name=''theProjectName'',
version=''1'',
packages=[''thePackage''],
url='''',
license='''',
author=''me'',
author_email=''[email protected]'',
description='''',
options={''bdist_rpm'': {''install_script'': ''filewithinstallcommands''}},
)
archivo - MANIFEST.in:
include license.txt
file - filewithinstallcommands:
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
cree MANIFEST.in
en la raíz del proyecto con recursive-include
en el directorio requerido o include
con el nombre del archivo.
include LICENSE
include README.rst
recursive-include package/static *
recursive-include package/templates *
Para lograr lo que describes, tomarás dos pasos ...
- El archivo debe agregarse al tarball de origen
- setup.py necesita ser modificado para instalar el archivo de datos en la ruta fuente
Paso 1: Para agregar el archivo al tarball de origen, inclúyalo en 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 tarball fuente.
Aquí se muestra el MANIFIESTO de mi proyecto:
- CHANGELOG.txt
- INSTALL.txt
- LICENSE.txt
- pypreprocessor.py
- README.txt
- setup.py
- test.py
- TODO.txt
Nota: Si bien 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, necesita 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 la de los archivos de origen.
Para modificar el directorio de instalación de datos para que coincida con el directorio de instalación de origen ...
Extraiga 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 setup ():
data_files=[('''', [''LICENSE.txt''])]
Nota: Los pasos anteriores deben cumplir exactamente lo que describió de manera estándar sin requerir ninguna biblioteca de extensión.