Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Managing resources in a Python project

I have a Python project in which I am using many non-code files. Currently these are all images, but I might use other kinds of files in the future. What would be a good scheme for storing and referencing these files?

I considered just making a folder "resources" in the main directory, but there is a problem; Some images are used from within sub-packages of my project. Storing these images that way would lead to coupling, which is a disadvantage.

Also, I need a way to access these files which is independent on what my current directory is.

like image 492
Ram Rachum Avatar asked Sep 08 '09 18:09

Ram Rachum


People also ask

How do you organize a Python module?

Organize your modules into packages. Each package must contain a special __init__.py file. Your project should generally consist of one top-level package, usually containing sub-packages. That top-level package usually shares the name of your project, and exists as a directory in the root of your project's repository.

What is __ init __ py in Python?

The __init__.py files are required to make Python treat the directories as containing packages; this is done to prevent directories with a common name, such as string, from unintentionally hiding valid modules that occur later on the module search path.


1 Answers

You may want to use pkg_resources library that comes with setuptools.

For example, I've made up a quick little package "proj" to illustrate the resource organization scheme I'd use:

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 

Notice how I keep all resources in a separate subpackage.

"code.py" shows how pkg_resources is used to refer to the resource objects:

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

If you run it, you get:

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

If you need to treat a resource as a fileobject, use resource_stream().

The code accessing the resources may be anywhere within the subpackage structure of your project, it just needs to refer to subpackage containing the images by full name: proj.resources.images, in this case.

Here's "setup.py":

#!/usr/bin/env python  from setuptools import setup, find_packages  setup(name='proj',       packages=find_packages(),       package_data={'': ['*.png']}) 

Caveat: To test things "locally", that is w/o installing the package first, you'll have to invoke your test scripts from directory that has setup.py. If you're in the same directory as code.py, Python won't know about proj package. So things like proj.resources won't resolve.

like image 104
Pavel Repin Avatar answered Oct 05 '22 21:10

Pavel Repin