2009-09-08 16 views
26

Ho un progetto Python in cui sto utilizzando molti file non di codice. Attualmente queste sono tutte immagini, ma potrei usare altri tipi di file in futuro. Quale sarebbe un buon schema per archiviare e referenziare questi file?Gestione delle risorse in un progetto Python

Ho pensato di creare una cartella "risorse" nella directory principale, ma c'è un problema; Alcune immagini sono utilizzate all'interno di sotto-pacchetti del mio progetto. Conservare queste immagini in questo modo porterebbe all'accoppiamento, che è uno svantaggio.

Inoltre, ho bisogno di un modo per accedere a questi file che è indipendente da ciò che è la mia directory corrente.

risposta

34

È possibile utilizzare la libreria pkg_resources fornita con setuptools.

Per esempio, ho fatto un piccolo pacchetto rapido "proj" per illustrare lo schema di organizzazione delle risorse userei:

proj/setup.py 
proj/proj/__init__.py 
proj/proj/code.py 
proj/proj/resources/__init__.py 
proj/proj/resources/images/__init__.py 
proj/proj/resources/images/pic1.png 
proj/proj/resources/images/pic2.png 

Notate come continuo a tutte le risorse in un sottopacchetto separata.

"code.py" mostra come pkg_resources viene utilizzato per fare riferimento agli oggetti di risorse:

from pkg_resources import resource_string, resource_listdir 

# Itemize data files under proj/resources/images: 
print resource_listdir('proj.resources.images', '') 
# Get the data file bytes: 
print resource_string('proj.resources.images', 'pic2.png').encode('base64') 

Se lo si esegue, si ottiene:

['__init__.py', '__init__.pyc', 'pic1.png', 'pic2.png'] 
iVBORw0KGgoAAAANSUhE ... 

Se è necessario trattare una risorsa come FileObject, utilizzare resource_stream().

Il codice che accede alle risorse può essere ovunque all'interno della struttura del sottopacchetto del progetto, è sufficiente fare riferimento al pacchetto parziale contenente le immagini con il nome completo: proj.resources.images, in questo caso.

Ecco "setup.py":

#!/usr/bin/env python 

from setuptools import setup, find_packages 

setup(name='proj', 
     packages=find_packages(), 
     package_data={'': ['*.png']}) 

Caveat: per verificare le cose "a livello locale", che è w/o l'installazione del primo pacchetto, dovrete richiamare i vostri script di test dalla directory che ha setup.py . Se ti trovi nella stessa directory di code.py, Python non saprà del pacchetto proj. Quindi cose come proj.resources non risolveranno.

+1

Bene, qui gli svantaggi sono troppo. Non esiste un modo semplice e intelligente per mettere insieme le risorse con i progetti Python? –

+0

So solo 2 modi ampiamente supportati (non è semplice): 1) 'distutils'-way (standard): la documentazione lascia l'accesso ai file di risorse come esercizio per il lettore (probabilmente perché pensano che le manipolazioni del percorso relativo a '__file__' sono tutti necessari). 2) 'setuptools'-way (superset di' distutils'), descritto sopra. –

4

È sempre possibile avere una cartella "risorse" separata in ciascun sottopackage che ne ha bisogno, e utilizzare le funzioni os.path per ottenere questi valori dai sottopackaggi dello __file__. Per illustrare quello che voglio dire, ho creato il __init__.py seguente file in tre sedi:

 
c:\temp\topp  (top-level package) 
c:\temp\topp\sub1 (subpackage 1) 
c:\temp\topp\sub2 (subpackage 2) 

Ecco il file __init__.py:

import os.path 
resource_path = os.path.join(os.path.split(__file__)[0], "resources") 
print resource_path 

in c: \ temp \ lavoro, creo un app, topapp. py, come segue:

import topp 
import topp.sub1 
import topp.sub2 

Questa respresents l'applicazione utilizzando il pacchetto topp e sottopacchetti. Quindi lo eseguo:

 
C:\temp\work>topapp 
Traceback (most recent call last): 
    File "C:\temp\work\topapp.py", line 1, in 
    import topp 
ImportError: No module named topp 

Questo è come previsto. Abbiamo impostato la PYTHONPATH per simulare avere il nostro pacchetto sul percorso:

 
C:\temp\work>set PYTHONPATH=c:\temp 

C:\temp\work>topapp 
c:\temp\topp\resources 
c:\temp\topp\sub1\resources 
c:\temp\topp\sub2\resources 

Come si può vedere, i percorsi delle risorse risolti correttamente la posizione dei (sotto) i pacchetti sul percorso.

Aggiornamento:Here la documentazione Py2exe pertinente.

+0

Ma che dire di quando si vuole eseguire il py2exe? –

+0

Non stavo parlando di come impacchettare le risorse con il codice. Stavo parlando del fatto che '__file__' non funzionerà. –

1

@ pycon2009, c'era una presentazione su distutils e setuptools. Potete trovare tutti i video qui

Eggs and Buildout Deployment in Python - Part 1

Eggs and Buildout Deployment in Python - Part 2

Eggs and Buildout Deployment in Python - Part 3

In questi video, essi descrivono come includere risorse statiche nel pacchetto. Credo che sia nella parte 2.

Con setuptools, è possibile definire le dipendenze, questo consentirebbe di avere 2 pacchetti che utilizzano risorse dal 3 ° pacchetto.

Setuptools fornisce inoltre un metodo standard per accedere a queste risorse e consente di utilizzare percorsi relativi all'interno dei pacchetti, eliminando la necessità di preoccuparsi della posizione in cui sono installati i pacchetti.