Gestión de recursos en un proyecto Python
Tengo un proyecto Python en el que estoy usando muchos archivos que no son de código. Actualmente estas son todas las imágenes, pero podría usar otros tipos de archivos en el futuro. ¿Cuál sería un buen esquema para almacenar y hacer referencia a estos archivos?
Consideré simplemente hacer una carpeta "resources" en el directorio principal, pero hay un problema; Algunas imágenes se usan dentro de subpaquetes de mi proyecto. Almacenar estas imágenes de esa manera conduciría al acoplamiento, lo cual es una desventaja.
También, necesito un forma de acceder a estos archivos que es independiente de lo que mi directorio actual es.
3 answers
Es posible que desee utilizar la biblioteca pkg_resources
que viene con setuptools
.
Por ejemplo, he creado un pequeño paquete rápido "proj"
para ilustrar el esquema de organización de recursos que usaría:
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
Observe cómo mantengo todos los recursos en un subpaquete separado.
"code.py"
muestra cómo se usa pkg_resources
para referirse a los objetos de recurso:
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 lo ejecutas, obtienes: {[17]]}
['__init__.py', '__init__.pyc', 'pic1.png', 'pic2.png'] iVBORw0KGgoAAAANSUhE ...
Si necesita tratar un recurso como un objeto de archivo, utilice resource_stream()
.
El código el acceso a los recursos puede estar en cualquier lugar dentro de la estructura del subpaquete de su proyecto, solo necesita referirse al subpaquete que contiene las imágenes por nombre completo: proj.resources.images
, en este caso.
Aquí está "setup.py"
:
#!/usr/bin/env python
from setuptools import setup, find_packages
setup(name='proj',
packages=find_packages(),
package_data={'': ['*.png']})
Advertencia:
Para probar cosas "localmente", es decir sin instalar el paquete primero, tendrá que invocar sus scripts de prueba desde el directorio que tiene setup.py
. Si estás en el mismo directorio que code.py
, Python no sabrá sobre el paquete proj
. Así que cosas como proj.resources
no se resolverá.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-08 22:22:05
Siempre puede tener una carpeta separada de "recursos" en cada subpaquete que lo necesite, y usar las funciones os.path
para acceder a ellas desde los valores __file__
de sus subpaquetes. Para ilustrar lo que quiero decir, creé el siguiente archivo __init__.py
en tres ubicaciones:
c:\temp\topp (top-level package) c:\temp\topp\sub1 (subpackage 1) c:\temp\topp\sub2 (subpackage 2)
Aquí está el archivo __init__.py
:
import os.path
resource_path = os.path.join(os.path.split(__file__)[0], "resources")
print resource_path
En c:\temp\work, Creo una aplicación, topapp.py, según se indica:
import topp
import topp.sub1
import topp.sub2
Esto representa la aplicación usando el paquete y subpaquetes topp
. Entonces corro it:
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
Eso es lo esperado. Configuramos el PYTHONPATH para simular tener nuestro paquete en la ruta:
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
Como puede ver, las rutas de recurso se resolvieron correctamente a la ubicación de los (sub)paquetes reales en la ruta.
Actualizar: Aquí está la documentación correspondiente de py2exe.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-08 20:56:19
@ pycon2009, hubo una presentación sobre distutils y setuptools. Puedes encontrar todos los videos aquí
Despliegue de Eggs y Buildout en Python-Parte 1
Despliegue de Eggs y Buildout en Python-Parte 2
Despliegue de Eggs y Buildout en Python-Parte 3
En estos videos, describen cómo incluir recursos estáticos en su paquete. Creo que está en la parte 2.
Con setuptools, puede definir dependencias, esto le permitiría tener 2 paquetes que usan recursos de 3rd package.
Setuptools también le da una forma estándar de acceder a estos recursos y le permite usar rutas relativas dentro de sus paquetes, lo que elimina la necesidad de preocuparse por dónde están instalados sus paquetes.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-24 16:16:28