web-dev-qa-db-fra.com

Gestion des ressources dans un projet Python

J'ai un projet Python dans lequel j'utilise de nombreux fichiers non-code. Actuellement, ce sont toutes des images, mais je pourrais utiliser d'autres types de fichiers à l'avenir. Quel serait un bon schéma pour stocker et référencer ces fichiers?

J'ai envisagé de simplement créer un dossier "ressources" dans le répertoire principal, mais il y a un problème; Certaines images sont utilisées à partir de sous-packages de mon projet. Le stockage de ces images de cette manière entraînerait un couplage, ce qui est un inconvénient.

De plus, j'ai besoin d'un moyen d'accéder à ces fichiers qui est indépendant de mon répertoire actuel.

45
Ram Rachum

Vous souhaiterez peut-être utiliser la bibliothèque pkg_resources Fournie avec setuptools.

Par exemple, j'ai créé un petit package rapide "proj" Pour illustrer le schéma d'organisation des ressources que j'utiliserais:

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 

Remarquez comment je conserve toutes les ressources dans un sous-package séparé.

"code.py" Montre comment pkg_resources Est utilisé pour faire référence aux objets ressources:

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

Si vous l'exécutez, vous obtenez:

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

Si vous devez traiter une ressource comme un objet fichier, utilisez resource_stream().

Le code accédant aux ressources peut se trouver n'importe où dans la structure de sous-package de votre projet, il suffit de faire référence au sous-package contenant les images par leur nom complet: proj.resources.images, Dans ce cas.

Voici "setup.py":

#!/usr/bin/env python

from setuptools import setup, find_packages

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

Avertissement: Pour tester les choses "localement", c'est-à-dire sans installer le paquet en premier, vous devrez appeler vos scripts de test à partir du répertoire qui a setup.py. Si vous êtes dans le même répertoire que code.py, Python ne connaît pas le package proj. Donc, des choses comme proj.resources Ont gagné ' t résoudre.

52
Pavel Repin

Vous pouvez toujours avoir un dossier "ressources" distinct dans chaque sous-package qui en a besoin et utiliser os.path fonctions pour y accéder à partir du __file__ valeurs de vos sous-packages. Pour illustrer ce que je veux dire, j'ai créé ce qui suit __init__.py fichier à trois emplacements:

 c:\temp\topp (package de niveau supérieur) 
 c:\temp\topp\sub1 (sous-package 1) 
 c:\temp\topp\sub2 (sous-package 2 ) 

Ici se trouve le __init__.py fichier:

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

Dans c:\temp\work, je crée une application, topapp.py, comme suit:

import topp
import topp.sub1
import topp.sub2

Cela représente l'application utilisant le package et les sous-packages topp. Ensuite, je l'exécute:

 C:\temp\work> topapp 
 Traceback (dernier appel le plus récent): 
 Fichier "C:\temp\work\topapp.py", ligne 1, dans 
 import topp 
 ImportError: Aucun module nommé topp 

C'est comme prévu. Nous avons défini le PYTHONPATH pour simuler le fait d'avoir notre package sur le chemin:

 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 

Comme vous pouvez le voir, les chemins d'accès aux ressources se sont correctement résolus à l'emplacement des (sous-) packages réels sur le chemin d'accès.

Mise à jour: Ici est la documentation py2exe appropriée.

5
Vinay Sajip

@ pycon2009, il y a eu une présentation sur les distutils et les setuptools. Vous pouvez trouver toutes les vidéos ici

Eggs and Buildout Deployment in Python - Part 1

Eggs et déploiement de buildout dans Python - Partie 2

Eggs and Buildout Deployment in Python - Part

Dans ces vidéos, ils décrivent comment inclure des ressources statiques dans votre package. Je crois que c'est dans la partie 2.

Avec setuptools, vous pouvez définir des dépendances, cela vous permettrait d'avoir 2 packages qui utilisent les ressources du 3ème package.

Setuptools vous donne également un moyen standard d'accéder à ces ressources et vous permet d'utiliser des chemins relatifs à l'intérieur de vos packages, ce qui vous évite de vous soucier de l'emplacement d'installation de vos packages.

1
Taras Mankovski