MANIFEST.in ignorato su "python setup.py install" - nessun file di dati installato?


91

Ecco il mio script setup.py ridotto all'osso con materiale non di codice rimosso:

#!/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

Quando eseguo "python setup.py install sdist" ottengo un bel .tar.gz con una cartella principale "whyteboard-0.41", con le mie cartelle locali / images / e whyteboard-help /. Questo ha anche il mio script whyteboard.py che avvia il mio programma dall'interno del pacchetto sorgente whyteboard.

Così:

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

Questo rispecchia il codice sorgente del mio programma, è come dovrebbe essere tutto ed è corretto.

Tuttavia, quando eseguo "python setup.py install" nessuno dei miei file di dati viene scritto - solo il pacchetto sorgente "whyteboard" e whyteboard.py si trova in /usr/local/lib/python2.6/dist-packages/ .

Idealmente, vorrei che la stessa struttura di directory di ciò che è stato generato nel file .tar.gz venisse creata in dist-packages, poiché è così che il mio programma si aspetta di cercare le sue risorse.

Come posso ottenere "installa" per creare questa struttura di directory? Sembra che stia ignorando il mio file manifest, per quanto ne so.


Risposte:


30

Alcune note in aggiunta alla risposta di Ned (che colpisce il problema principale):

Distutils non installa pacchetti e moduli Python all'interno di una sottodirectory per progetto all'interno site-packages(o dist-packagessu Debian / Ubuntu): vengono installati direttamente in site-packages, come hai visto. Quindi la whyteboard-xxdirectory contenente nel tuo sdist non esisterà nella forma installata finale.

Un'implicazione di ciò è che dovresti fare attenzione a nominare il tuo data_filesin un modo che chiarisca a quale progetto appartengono, perché quei file / directory sono installati direttamente nella site-packagesdirectory globale , non all'interno diwhyteboard directory .

Oppure potresti invece creare i tuoi dati package_datadel whyteboardpacchetto (il che significa che deve risiedere all'interno di quel pacchetto, cioè accanto a__init__.py ), e quindi questo non è un problema.

Infine, non ha molto senso avere sia un whyteboard.pymodulo in py_modulesche un whyteboard/__init__.pypacchetto in packages. I due si escludono a vicenda e, se li hai entrambi, il filewhyteboard.py modulo verrà ignorato dalle importazioni a favore del pacchetto con lo stesso nome.

Se whyteboard.pyè solo uno script e non deve essere importato, è necessario utilizzare l' opzione script e rimuoverlo da py_modules.


1
È un peccato. Non mi piace l'idea di avere i dati del pacchetto: per me ha più senso che quelle risorse vivano al di fuori della directory dei sorgenti. Né mi piace dover avere il prefisso dei nomi delle directory con il nome del programma (anche se lo faccio già per i file di aiuto). Hmm ..
Steven Sproat il

68

MANIFEST.indice a Distutils quali file includere nella distribuzione dei sorgenti ma non influisce direttamente sui file installati. Per questo è necessario includere i file appropriati nel setup.pyfile, generalmente come dati del pacchetto o come file aggiuntivi .


Ho provato ad aggiungere un elenco di dati del pacchetto ma nessuno dei file che ho specificato è stato utilizzato. Non ero sicuro che le posizioni dei file fossero installate rispetto all'installazione complessiva del pacchetto. Comunque, non stava ancora scrivendo i miei file nella corretta struttura di directory che mi aspettavo.
Steven Sproat

La documentazione collegata in questa risposta ti fornisce tutte le informazioni necessarie su dove sono installati data_files e package_data. Se queste opzioni non funzionano per te, aggiorna la tua domanda con la sintassi esatta che hai provato, i risultati e ciò che ti aspettavi.
Carl Meyer

4
Questo funziona per me: duplicare le mie voci MANIFEST.in all'interno di data_packages di setup.py fa funzionare tutto. Grazie Ned, sono anni che non riesco a capire questo punto. Spero che ora le mie esperienze di distutils / setuptools / distribute abbiano più senso.
Jonathan Hartley

7
Questo progetto di poter includere file nel pacchetto che non verranno installati ha senso? Quando verrà utilizzato?
Roger Dahl

29

Non riuscivo a capire perché il mio MANIFEST.infile veniva ignorato durante l'esecuzione python setup.py install: si è scoperto che include_package_data=Truerisolve il problema. L' package_dataopzione non è effettivamente richiesta.


buona cattura, perché include_package_data=Truenon è il valore predefinito?
liang

9

Dovresti usare 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'],
)

Questo non sta effettivamente utilizzando il file MANIFEST per eseguire il lavoro, ma include tutti i file necessari.


Questo ha funzionato per me con setuptools . Creo il pacchetto Debian e vedo i miei file glade elencati nel package_datadizionario apparire nel posto giusto solo dopo averli aggiunti include_package_data=Tru.
mlt

8

Eseguendo python 2.6.1 su Mac OSX, non ho avuto assolutamente fortuna se non usando data_files parametro in setup.py. Tutto con MANIFEST.in portava semplicemente a includere dei file nel pacchetto dist, ma mai installati. Ho controllato alcuni altri pacchetti e in effetti stavano usando data_files per specificare file aggiuntivi.

Ho creato una breve funzione per aiutare a enumerare tutti i file da un albero di directory nel file

(target_dir, [file list]) formato previsto da 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

Ora posso semplicemente chiamarlo all'interno della mia chiamata di configurazione:

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

E tutto in quegli alberi viene installato.


11
È fantastico, ma dove viene installato? Per me, quando uso "pip install", i miei data_files vanno nella root del mio virtualenv (cioè una singola directory condivisa da tutti i pacchetti di virtualenv.) Se usi "setup.py install", i miei data_files vanno in "site- packages / <mypackage> .egg / ". Se i file sono dati necessari in fase di esecuzione, in nessun caso è banale per il mio codice trovare questi file e, naturalmente, devo cercare in entrambe le directory in fase di esecuzione. Se i file sono il mio file LICENSE, in nessun caso è banale per i miei utenti arrivare dalla mia fonte alla LICENCE. Perplesso.
Jonathan Hartley

4

Minimo esempio eseguibile pubblicato

Key takeaway: ha MANIFEST.infunzionato solo per me, package_datano.

Testato su Ubuntu 19.10, Python 3.7.5, wheel == 0.32.3, setuptools == 41.1.0, twine == 3.1.1.

In che modo gli utenti finali utilizzano il pacchetto da https://pypi.org/project/python-sample-package-with-data/ :

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

Uscita prevista:

hello data

Come lo pubblicano i manutentori:

# 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

I file effettivi:

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

python-sample-package-with-data

#!/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='ciro.santilli.contact@gmail.com',
    packages=find_packages(),
    include_package_data=True,
    scripts=['python-sample-package-with-data'],
)

Bibliografia:

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.