MANIFEST.in ignoré lors de «l'installation de python setup.py» - aucun fichier de données installé?

89

Voici mon script setup.py dépouillé avec des éléments non codés supprimés:

#!/usr/bin/env python

from distutils.core import setup
from whyteboard.misc import meta


setup(
    name = 'Whyteboard',
    version = meta.version,

    packages = ['whyteboard', 'whyteboard.gui', 'whyteboard.lib', 'whyteboard.lib.pubsub',
                'whyteboard.lib.pubsub.core', 'whyteboard.lib.pubsub.utils', 'whyteboard.misc'],

    py_modules = ['whyteboard'],
    scripts = ['whyteboard.py'],
)

MANIFEST.in:

include *.txt
include whyteboard-help/*.*
recursive-include locale *.mo
recursive-include images *.png

Quand j'exécute "python setup.py install sdist", j'obtiens un joli .tar.gz avec un dossier racine "whyteboard-0.41", avec mes dossiers locale / images / et whyteboard-help / à l'intérieur. Cela a également mon script whyteboard.py qui lance mon programme depuis le paquet source whyteboard.

Donc:

whyteboard/
 ├── locale/
 ├── images
 ├── whyteboard-help/
 ├── whyteboard/
 │  ├── __init__.py
 │  └── other packages etc
 ├── whyteboard.py
 ├── README
 ├── setup.py
 └── CHANGELOG

Cela reflète la source de mon programme, est la façon dont tout devrait être et est correct.

Cependant, lorsque j'exécute "python setup.py install", aucun de mes fichiers de données n'est écrit - seul le paquet source "whyteboard", et le whyteboard.py est placé dans /usr/local/lib/python2.6/dist-packages/ .

Idéalement, j'aimerais que la même structure de répertoires que ce qui a été généré dans le fichier .tar.gz soit créée dans dist-packages, car c'est ainsi que mon programme s'attend à rechercher ses ressources.

Comment puis-je obtenir "installer" pour créer cette structure de répertoires? Il semble ignorer mon fichier manifeste, pour autant que je sache.

Steven Sproat
la source

Réponses:

30

Quelques notes en plus de la réponse de Ned (qui touche au problème central):

Distutils n'installe pas les packages et modules Python dans un sous-répertoire par projet dans site-packages(ou dist-packagessur Debian / Ubuntu): ils sont installés directement dans site-packages, comme vous l'avez vu. Donc le contenantwhyteboard-xx répertoire dans votre sdist n'existera pas dans la forme finale installée.

Une implication de ceci est que vous devez faire attention à nommer votre data_filesd'une manière qui clarifie à quel projet ils appartiennent, car ces fichiers / répertoires sont installés directement dans le site-packagesrépertoire global , pas à l'intérieur d'un contenantwhyteboard répertoire .

Ou vous pouvez à la place faire vos données package_datadu whyteboardpaquet (ce qui signifie qu'il doit vivre à l'intérieur de ce paquet, c'est-à-dire à côté de __init__.py), et alors ce n'est pas un problème.

Enfin, cela n'a pas beaucoup de sens d'avoir à la fois un whyteboard.pymodule dans py_moduleset un whyteboard/__init__.pypackage dans packages. Les deux sont mutuellement exclusifs, et si vous avez les deux, le whyteboard.pymodule sera ignoré par les importations au profit du package du même nom.

S'il ne whyteboard.pys'agit que d'un script et n'est pas destiné à être importé, vous devez utiliser l' option scripts pour celui-ci et le supprimer py_modules.

Carl Meyer
la source
1
C'est malheureux. Je n'aime pas l'idée d'avoir des données de package - pour moi, il est plus logique que ces ressources vivent en dehors du répertoire source. Je n'aime pas non plus avoir des noms de répertoire préfixés avec le nom du programme (même si je le fais déjà pour les fichiers d'aide). Hmm ..
Steven Sproat
67

MANIFEST.inindique à Distutils quels fichiers inclure dans la distribution source mais cela n'affecte pas directement les fichiers installés. Pour cela, vous devez inclure les fichiers appropriés dans le setup.pyfichier, généralement sous forme de données de package ou de fichiers supplémentaires .

Ned Deily
la source
J'ai essayé d'ajouter une liste de données de package mais aucun des fichiers que j'ai spécifiés n'a été utilisé. Je ne savais pas si les emplacements des fichiers étaient installés par rapport à l'installation globale du package. Quoi qu'il en soit, il n'écrivait toujours pas mes fichiers dans la bonne structure de répertoires que j'attendais.
Steven Sproat
La documentation liée à cette réponse vous donne toutes les informations dont vous avez besoin sur l'emplacement d'installation des data_files et package_data. Si ces options ne fonctionnent pas pour vous, veuillez mettre à jour votre question avec la syntaxe exacte que vous avez essayée, les résultats et ce que vous attendiez.
Carl Meyer
4
Cela fonctionne pour moi: Dupliquer mes entrées MANIFEST.in dans les data_packages de setup.py fait que tout fonctionne. Merci Ned - je n'ai pas compris ce point pendant des années. J'espère que maintenant mes expériences distutils / setuptools / distribueront plus de sens.
Jonathan Hartley
7
Cette conception consistant à pouvoir inclure des fichiers dans le package qui ne seront pas installés a-t-elle un sens? Quand serait-il utilisé?
Roger Dahl
28

Je ne pouvais pas comprendre pourquoi mon MANIFEST.infichier était ignoré lorsque j'ai couru python setup.py install- il s'avère que include_package_data=Truele problème est résolu. L' package_dataoption n'est pas réellement requise.

Greg
la source
bonne prise, pourquoi include_package_data=Truen'est pas la valeur par défaut?
liang
9

Vous devez utiliser setuptools:

#!/usr/bin/env python

from setuptools import setup, find_packages
from whyteboard.misc import meta


setup(
  name = 'Whyteboard',
  version = meta.version,

  packages = find_packages(),
  include_package_data=True,

  py_modules = ['whyteboard'],
  scripts = ['whyteboard.py'],
)

Cela n'utilise pas réellement le fichier MANIFEST pour faire le travail, mais il inclut tous les fichiers nécessaires.

Juho Rutila
la source
Cela a fonctionné pour moi avec setuptools . Je construis le paquet Debian et je vois mes fichiers glade listés dans le package_datadictionnaire apparaître au bon endroit seulement après avoir ajouté include_package_data=Tru.
mlt le
8

En exécutant python 2.6.1 sur Mac OSX, je n'ai absolument pas eu de chance sauf en utilisant les data_files paramètre dans setup.py. Tout avec MANIFEST.in aboutissait simplement à ce que des fichiers soient inclus dans le paquet dist, mais jamais installés. J'ai vérifié d'autres paquets et ils utilisaient en effet des data_files pour spécifier des fichiers supplémentaires.

J'ai créé une fonction courte pour aider à énumérer tous les fichiers d'une arborescence de répertoires dans le

(target_dir, [file list]) format attendu par data_files:

def gen_data_files(*dirs):
    results = []

    for src_dir in dirs:
        for root,dirs,files in os.walk(src_dir):
            results.append((root, map(lambda f:root + "/" + f, files)))
    return results

Maintenant, je peux simplement appeler cela dans mon appel de configuration:

setup(... data_files = gen_data_files("docs", "lib") ...

Et tout dans ces arbres est installé.

Scott Persinger
la source
11
C'est génial, mais où est-il installé? Pour moi, lorsque j'utilise "pip install", mes data_files vont à la racine de mon virtualenv (c'est-à-dire un répertoire unique partagé par tous les packages de virtualenv.) Si vous utilisez "setup.py install", alors mes data_files vont dans "site- packages / <mypackage> .egg / ". Si les fichiers sont des données nécessaires à l'exécution, dans aucun des cas, il n'est trivial pour mon code de trouver ces fichiers, et bien sûr, je dois rechercher les deux répertoires au moment de l'exécution. Si les fichiers sont mon fichier de LICENCE, dans aucun des cas, il n'est trivial pour mes utilisateurs d'obtenir de ma source à la LICENCE. Perplexe.
Jonathan Hartley
3

Exemple exécutable publié minimal

Points clés à retenir: n'a MANIFEST.infonctionné que pour moi, package_datapas.

Testé sur Ubuntu 19.10, Python 3.7.5, roue == 0.32.3, setuptools == 41.1.0, twine == 3.1.1.

Comment les utilisateurs finaux utilisent le package de https://pypi.org/project/python-sample-package-with-data/ :

python3 -m pip install --user python-sample-package-with-data
python-sample-package-with-data

Production attendue:

hello data

Comment les responsables le publient:

# One time setup.
python3 -m pip install --user setuptools wheel twine

# Every time you want to publish.
python setup.py sdist bdist_wheel
twine upload dist/*
rm -rf build dist *.egg-info

Les fichiers réels:

MANIFEST.in

# Or else pip install cannot find README.md on the setup.py under certain conditions.
include README.md

# This actually adds the data file.
include python_sample_package_with_data/mydata.txt

échantillon-python-package-avec-données

#!/usr/bin/env python3

import python_sample_package_with_data

print(python_sample_package_with_data.get_data(), end='')

python_sample_package_with_data / __ init__.py

try:
    import importlib.resources as importlib_resources
except ImportError:
    # In PY<3.7 fall-back to backported `importlib_resources`.
    import importlib_resources

def get_data():
    return importlib_resources.read_text(__name__, 'mydata.txt')

python_sample_package_with_data / mydata.txt

hello data

setup.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from setuptools import setup, find_packages

from os import path
this_directory = path.abspath(path.dirname(__file__))
with open(path.join(this_directory, 'README.md')) as f:
    long_description = f.read()

setup(
    name='python-sample-package-with-data',
    version='0.0.3',
    description='My short description',
    long_description=long_description,
    long_description_content_type='text/markdown',
    url='https://github.com/cirosantilli/python-sample-package-with-data',
    author='Ciro Santilli',
    author_email='[email protected]',
    packages=find_packages(),
    include_package_data=True,
    scripts=['python-sample-package-with-data'],
)

Bibliographie:

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
la source