Compresi file non Python con setup.py
Domanda
Come posso includere setup.py
in un file che non fa parte del codice? (In particolare, è un file di licenza, ma potrebbe essere qualsiasi altra cosa.)
Voglio essere in grado di controllare la posizione del file. Nella cartella di origine originale, il file si trova nella radice del pacchetto. (cioè allo stesso livello del __init__.py
più in alto.) Voglio che rimanga esattamente lì quando il pacchetto è installato, indipendentemente dal sistema operativo. Come posso farlo?
Soluzione
Probabilmente il modo migliore per farlo è usare la direttiva setuptools
package_data
. Questo significa usare setuptools
(o distribut
) invece di distutils
, ma questo è molto semplice e quot ; aggiornamento ".
Ecco un esempio completo (ma non testato):
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=[],
)
Nota le linee specifiche che sono fondamentali qui:
package_data={'': ['license.txt']},
include_package_data=True,
package_data
è un dict
di nomi di pacchetti (vuoto = tutti i pacchetti) in un elenco di modelli (può includere globs). Ad esempio, se vuoi specificare solo i file all'interno del tuo pacchetto, puoi farlo anche tu:
package_data={'yourpackage': ['*.txt', 'path/to/resources/*.txt']}
La soluzione qui è sicuramente non per rinominare i tuoi file non py
con l'estensione .py
.
Vedi La presentazione di Ian Bicking per maggiori informazioni.
AGGIORNAMENTO: un altro approccio [migliore]
Un altro approccio che funziona bene se si desidera solo controllare il contenuto della distribuzione di origine ( sdist
) e disporre di file all'esterno del pacchetto (ad esempio directory di livello superiore) è aggiungere un
Da quando ho scritto questa risposta, ho scoperto che l'utilizzo di MANIFEST.in
è in genere un approccio meno frustrante per assicurarsi solo che la distribuzione dei sorgenti ( tar.gz
) abbia file necessari.
Ad esempio, se si desidera includere il requisito.txt
dal livello più alto, includere ricorsivamente i dati "quotazione" di livello superiore; directory:
include requirements.txt
recursive-include data *
Tuttavia, per poter copiare questi file al momento dell'installazione nella cartella del pacchetto all'interno dei pacchetti del sito, è necessario fornire include_package_data = True
in setup ()
funzione. Vedi Aggiunta di file non di codice per ulteriori informazioni.
Altri suggerimenti
Per realizzare ciò che stai descrivendo ci vorranno due passaggi ...
- Il file deve essere aggiunto al tarball di origine
- setup.py deve essere modificato per installare il file di dati nel percorso di origine
Passaggio 1: per aggiungere il file al tarball di origine, includerlo nel MANIFEST
Crea un MANIFEST nella cartella che contiene setup.py
MANIFEST è fondamentalmente un file di testo con un elenco di tutti i file che verranno inclusi nel tarball di origine.
Ecco come appare il MANIFEST per il mio progetto:
- changelog.txt
- INSTALL.txt
- LICENSE.txt
- pypreprocessor.py
- README.txt
- setup.py
- test.py
- todo.txt
Nota: mentre sdist aggiunge alcuni file automaticamente , preferisco specificarli esplicitamente per essere sicuro invece di prevedere cosa fa e cosa no.
Passaggio 2: per installare il file di dati nella cartella di origine, modificare setup.py
Poiché stai cercando di aggiungere un file di dati (LICENSE.txt) alla cartella di installazione di origine, devi modificare il percorso di installazione dei dati in modo che corrisponda al percorso di installazione di origine. Ciò è necessario perché, per impostazione predefinita, i file di dati sono installati in una posizione diversa rispetto ai file di origine.
Per modificare la directory di installazione dei dati in modo che corrisponda alla directory di installazione di origine ...
Estrai le informazioni sulla directory di installazione da distutils con:
from distutils.command.install import INSTALL_SCHEMES
Modifica la directory di installazione dei dati in modo che corrisponda alla directory di installazione di origine:
for scheme in INSTALL_SCHEMES.values():
scheme['data'] = scheme['purelib']
E aggiungi il file di dati e il percorso a setup ():
data_files=[('', ['LICENSE.txt'])]
Nota: i passaggi precedenti dovrebbero realizzare esattamente ciò che hai descritto in modo standard senza richiedere alcuna libreria di estensioni.
crea MANIFEST.in
nella radice del progetto con recursive-include
nella directory richiesta o include
con il nome del file.
include LICENSE
include README.rst
recursive-include package/static *
recursive-include package/templates *
In setup.py in setup (:
setup(
name = 'foo library'
...
package_data={
'foolibrary.folderA': ['*'], # All files from folder A
'foolibrary.folderB': ['*.txt'] #All text files from folder B
},
Ecco una risposta più semplice che ha funzionato per me.
Innanzitutto, per un commento di Python Dev sopra, setuptools non è richiesto:
package_data is also available to pure distutils setup scripts
since 2.3. – Éric Araujo
È fantastico perché mettere un requisito setuptools sul pacchetto significa che dovrai installarlo anche. In breve:
from distutils.core import setup
setup(
# ...snip...
packages = ['pkgname'],
package_data = {'pkgname': ['license.txt']},
)
Passaggio 1: crea un file MANIFEST.in
nella stessa cartella con setup.py
Passaggio 2: includere il percorso relativo dei file che si desidera aggiungere in MANIFEST.in
include README.rst
include docs/*.txt
include funniest/data.json
Passaggio 3: impostare include_package_data = True
nella funzione setup ()
per copiare questi file nel pacchetto del sito
Volevo solo dare seguito a qualcosa che ho trovato lavorando con Python 2.7 su Centos 6. L'aggiunta di package_data o data_files come menzionato sopra non ha funzionato per me. Ho aggiunto un MANIFEST.IN con i file desiderati che hanno inserito i file non Python nel tarball, ma non li ho installati sul computer di destinazione tramite RPM.
Alla fine, sono stato in grado di ottenere i file nella mia soluzione utilizzando le "opzioni" nei setup / setuptools. I file delle opzioni consentono di modificare varie sezioni del file delle specifiche da setup.py. Come segue.
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'}},
)
file - MANIFEST.in:
include license.txt
file - file con i comandi di installazione:
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
Volevo pubblicare un commento a una delle domande, ma non ho abbastanza reputazione per farlo >. >
Ecco cosa ha funzionato per me (mi è venuto in mente dopo aver fatto riferimento ai documenti):
package_data={
'mypkg': ['../*.txt']
},
include_package_data: False
L'ultima riga è stata, stranamente, anche cruciale per me (puoi anche omettere questo argomento della parola chiave - funziona allo stesso modo)
Ciò che fa è copiare tutti i file di testo nella directory principale o principale (a un livello superiore dal pacchetto mypkg
che si desidera distribuire).
Spero che questo aiuti!
Ho risolto il problema: ho rinominato il mio lgpl2.1_license.txt
in lgpl2.1_license.txt.py
e ho inserito tre triple tra virgolette nel testo. Ora non ho bisogno di usare l'opzione data_files
né specificare percorsi assoluti. Renderlo un modulo Python è brutto, lo so, ma lo considero meno brutto che specificare percorsi assoluti.