2009-09-08 7 views
26

Ich habe ein Python-Projekt, in dem ich viele Nicht-Code-Dateien verwende. Momentan sind das alle Bilder, aber ich könnte in Zukunft andere Arten von Dateien verwenden. Was wäre ein gutes Schema zum Speichern und Referenzieren dieser Dateien?Verwalten von Ressourcen in einem Python-Projekt

Ich überlegte, nur einen Ordner "Ressourcen" im Hauptverzeichnis zu machen, aber es gibt ein Problem; Einige Bilder werden aus Teilpaketen meines Projekts verwendet. Das Speichern dieser Bilder würde zu einer Kopplung führen, was ein Nachteil ist.

Ich brauche auch eine Möglichkeit, auf diese Dateien zuzugreifen, die unabhängig davon ist, was mein aktuelles Verzeichnis ist.

Antwort

34

Möglicherweise möchten Sie pkg_resources Bibliothek verwenden, die mit setuptools kommt.

Zum Beispiel habe ich ein schnelles kleines Paket "proj" gemacht, um das Ressourcenorganisationsschema zu illustrieren ich verwenden würde:

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 

Beachten Sie, wie ich alle Ressourcen halte in einem separaten subpackage.

"code.py" zeigt, wie pkg_resources auf die Ressourcenobjekte zu bezeichnen ist:

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') 

Wenn Sie es ausführen, erhalten Sie:

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

Wenn Sie eine Ressource als Fileobject behandeln müssen, Verwenden Sie resource_stream().

Der Code, um die Ressourcen zugreifen können überall innerhalb der subpackage Struktur Ihres Projekts sein, es muss nur durch vollständigen Namen die Bilder beziehen sich auf Subpackage enthalten: proj.resources.images, in diesem Fall.

Hier "setup.py":

#!/usr/bin/env python 

from setuptools import setup, find_packages 

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

Caveat: Um die Dinge zu testen "vor Ort", dh w/o das Paket zuerst installieren, werden Sie Ihre Test-Scripts aus dem Verzeichnis aufrufen müssen, die setup.py hat . Wenn Sie sich im selben Verzeichnis wie code.py befinden, weiß Python nichts über proj Paket. Dinge wie proj.resources werden nicht aufgelöst.

+1

Nun, die Nachteile hier sind zu viel. Gibt es nicht eine einfache Möglichkeit, Ressourcen mit Python-Projekten zu packen? –

+0

Ich kenne nur 2 weit verbreitete Wege (sie sind leider nicht einfach): 1) 'distutils-way (standard): Die Dokumentation lässt den Zugriff auf Ressourcendateien als Übung für den Leser (wahrscheinlich weil sie Pfadmanipulationen denken relativ zu '__file__' sind alles was man braucht). 2) 'setuptools'-Weg (Obermenge von' distutils'), oben beschrieben. –

4

Sie können jederzeit über einen separaten „Ressourcen“ Ordner in jeder subpackage haben, die es braucht, und os.path Funktionen verwenden, um diese von den __file__ Werten Ihres Subpackages zu erhalten. Um zu zeigen, was ich meine, habe ich die folgende __init__.py Datei an drei Standorten:

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

Hier ist die __init__.py Datei:

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

In c: \ temp \ Arbeit schaffe ich eine App, topapp. py, wie folgt:

import topp 
import topp.sub1 
import topp.sub2 

Diese respresents die Anwendung mit dem Paket topp und Subpakete. Dann führe ich es:

 
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 

Das ist wie erwartet. Wir setzen den PYTHONPATH unser Paket zu simulieren, die auf dem Weg:

 
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 

Wie Sie sehen können, die richtig an den Ort der tatsächlichen (sub) Pakete auf dem Weg aufgelöst Ressourcenpfade.

Update:Here ist die relevante py2exe Dokumentation.

+0

Aber was ist, wenn Sie py2exe die ganze Sache wollen? –

+0

Ich habe nicht darüber gesprochen, wie man die Ressourcen mit dem Code packt. Ich habe darüber gesprochen, dass '__file__' nicht funktionieren wird. –

1

@ pycon2009 gab es eine Präsentation über Distutils und setuptools. Sie können alle Videos hier

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 diesen Videos finden, die sie beschreiben, wie statische Ressourcen in Ihrem Paket enthalten sein. Ich glaube, es ist in Teil 2.

Mit setuptools können Sie Abhängigkeiten definieren, dies würde Ihnen ermöglichen, 2 Pakete zu haben, die Ressourcen aus dem 3. Paket verwenden.

Setuptools bietet Ihnen außerdem eine Standardmethode für den Zugriff auf diese Ressourcen und ermöglicht Ihnen die Verwendung relativer Pfade innerhalb Ihrer Pakete, sodass Sie sich keine Gedanken darüber machen müssen, wo Ihre Pakete installiert sind.