web-dev-qa-db-fra.com

Comment ajouter des fichiers supplémentaires à une roue?

Comment contrôler quels fichiers sont inclus dans une roue? Il semble que MANIFEST.in n'est pas utilisé par python setup.py bdist_wheel.

METTRE À JOUR:

Je me suis trompé sur la différence entre l’installation à partir d’une archive source et d’une roue. La distribution source inclut les fichiers spécifiés dans MANIFEST.in, mais le package installé ne contient que des fichiers python. Des étapes sont nécessaires pour identifier les fichiers supplémentaires à installer, que ce soit via la distribution source, Egg ou wheel. À savoir, package_data est nécessaire pour les fichiers de package supplémentaires et data_files pour les fichiers hors de votre package, tels que les scripts de ligne de commande ou les fichiers de configuration système.

Question originale

J'ai un projet où j'utilise python setup.py sdist pour construire mon paquet, MANIFEST.in pour contrôler les fichiers inclus et exclus, et pyroma et check-manifest pour confirmer mes paramètres.

Je l’ai récemment convertie en double code Python 2/3 et j’ai ajouté un fichier setup.cfg avec

[bdist_wheel]
universal = 1

Je peux construire une roue avec python setup.py bdist_wheel, et cela semble être une roue universelle, comme vous le souhaitez. Cependant, il n'inclut pas tous les fichiers spécifiés dans MANIFEST.in

Qu'est-ce qui est installé?

J'ai creusé plus profondément et en sais maintenant plus sur l'emballage et la roue. Voici ce que j'ai appris:

Je télécharge deux fichiers de package dans le projet multigtfs sur PyPi :

  • multigtfs-0.4.2.tar.gz - la balle tar source, qui inclut tous les fichiers dans MANIFEST.in.
  • multigtfs-0.4.2-py2.py3-none-any.whl - La distribution binaire en question.

J'ai créé deux nouveaux environnements virtuels, tous deux avec Python 2.7.5, et installé chaque paquet (pip install multigtfs-0.4.2.tar.gz). Les deux environnements sont presque identiques. Ils ont différents fichiers .pyc, qui sont les fichiers Python "compilés". Il existe des fichiers journaux qui enregistrent les différents chemins sur le disque. L'installation à partir de la boule de tar source comprend un dossier multigtfs-0.4.2-py27.Egg-info, détaillant l'installation, et l'installation de la roue a un dossier multigtfs-0.4.2.dist-info, avec les détails de ce processus. Cependant, du point de vue du code utilisant le projet multigtfs, il n'y a pas de différence entre les deux méthodes d'installation.

De manière explicite, ni les fichiers .Zip utilisés par mon test, la suite de tests échouera:

$ Django-admin startproject demo
$ cd demo
$ pip install psycopg2  # DB driver for PostGIS project
$ createdb demo         # Create PostgreSQL database
$ psql -d demo -c "CREATE EXTENSION postgis" # Make it a PostGIS database 
$ vi demo/settings.py   # Add multigtfs to INSTALLED_APPS,
                        # Update DATABASE to set ENGINE to Django.contrib.gis.db.backends.postgis
                        # Update DATABASE to set NAME to test
$ ./manage.py test multigtfs.tests  # Run the tests
...
IOError: [Errno 2] No such file or directory: u'/Users/john/.virtualenvs/test/lib/python2.7/site-packages/multigtfs/tests/fixtures/test3.Zip'

Spécification de fichiers supplémentaires

En utilisant les suggestions des réponses, j’ai ajouté quelques directives supplémentaires à setup.py:

from __future__ import unicode_literals
# setup.py now requires some funky binary strings
...
setup(
    name='multigtfs',
    packages=find_packages(),
    package_data={b'multigtfs': ['test/fixtures/*.Zip']},
    include_package_data=True,
    ...
)

Cela installe les fichiers Zip (ainsi que le fichier README) dans le dossier et les tests s’exécutent désormais correctement. Merci pour les suggestions!

42
jwhitlock

Avez-vous essayé d'utiliser package_data dans votre setup.py? MANIFEST.in semble ciblé pour les versions de python <= 2.6, je ne suis pas sûr que les versions les plus récentes l'examinent même.

Après avoir exploré https://github.com/pypa/sampleproject , leur MANIFEST.in indique:

# If using Python 2.6 or less, then have to include package data, even though
# it's already declared in setup.py
include sample/*.dat

ce qui semble impliquer que cette méthode est obsolète. Pendant ce temps, dans setup.py ils déclarent:

setup(
    name='sample',
    ...
    # If there are data files included in your packages that need to be
    # installed, specify them here.  If using Python 2.6 or less, then these
    # have to be included in MANIFEST.in as well.
    package_data={
        'sample': ['package_data.dat'],
    },
    ...
)

(Je ne sais pas pourquoi ils ont choisi un caractère générique dans MANIFEST.in et un nom de fichier dans setup.py. Ils font référence au même fichier)

Ce qui, en plus d’être plus simple, semble impliquer à nouveau que la route package_data est supérieure à la méthode MANIFEST.in. Eh bien, à moins que vous n'ayez à supporter 2.6, c'est-à-dire, mes prières vont à vous.

26
vgel

Avant d'apporter des modifications dans MANIFEST.in ou setup.py, vous devez supprimer les anciens répertoires de sortie. Setuptools met en cache certaines des données, ce qui peut entraîner des résultats inattendus.

rm -rf build *.Egg-info

Si vous ne le faites pas, attendez-vous à ce que rien ne fonctionne correctement.

Maintenant, c'est hors du chemin.

  1. Si vous construisez une distribution source (sdist), vous pouvez utiliser n’importe quelle méthode ci-dessous.

  2. Si vous construisez un wheel (bdist_wheel), alors include_package_data et MANIFEST.in sont ignorés et vous devez utiliser package_data et data_files.

INCLUDE_PACKAGE_DATA

C’est une bonne option, mais bdist_wheel ne l’honore pas.

setup(
    ...
    include_package_data=True
)

# MANIFEST.in
include package/data.json

DATA_FILES pour les données hors package

C'est l'option la plus flexible car vous pouvez ajouter n'importe quel fichier de votre référentiel à un sdist ou bdist_wheel

setup(
    ....
    data_files=[
        ('output_dir':['conf/data.json']),
    ]
    # For sdist, output_dir is ignored!
    #
    # For bdist_wheel, data.json from conf dir in root of your repo 
    # and stored at `output_dir/` inside of the sdist package.
)

PACKAGE_DATA pour les fichiers non python à l'intérieur du package

Semblable à ce qui précède, mais pour un bdist_wheel, vous pouvez placer vos fichiers de données à l'intérieur du paquet. Il est identique pour sdist mais a plus de limitations que data_files car les fichiers ne peuvent être source que depuis votre sous-répertoire de package.

setup(
    ...
    package_data={'package':'data.json'},
    # data.json must be inside of your actual package
)
10
cmcginty

Vous pouvez spécifier des fichiers supplémentaires à installer à l'aide de la directive data_files . Est-ce ce que vous cherchez? Voici un petit exemple:

from setuptools import setup
from glob import glob

setup(
    name='extra',
    version='0.0.1',
    py_modules=['extra'],
    data_files=[
        ('images', glob('assets/*.png')),
    ],
)
10
lazy1

Vous pouvez utiliser package_data et data_files dans setup.py pour spécifier des fichiers supplémentaires, mais ils sont ridiculement difficiles à comprendre (et bogués) .

Une alternative consiste à utiliser MANIFEST.in et à ajouter include_package_data=True dans setup() de votre setup.py comme indiqué ici .

Avec cette directive, le MANIFEST.in sera utilisé pour spécifier les fichiers à inclure non seulement dans le fichier source tarball/Zip, mais également dans les programmes d'installation wheel et win32. Cela fonctionne aussi avec n’importe quelle version de Python (j’ai testé sur un projet de py2.6 à py3.6).

9
gaborous

J'avais config/répertoire avec des fichiers JSON, que je devais ajouter à la roue. J'ai donc ajouté ces lignes à MANIFEST.in:

recursive-include config/ *.json

La directive suivante à setup.py:

setup(
 ...
 include_package_data=True,
)

Et rien n'a fonctionné . Jusqu'à ce que je crée un fichier vide appelé __init__.py dans le répertoire config/.

(Python 3.6.7, molette 3.6.7, setuptools 39.0.1)

0
michael