Reputation: 44719
How do I reference a file relatively to a package's directory?
My directory structure is:
/foo package1/ resources/ __init__.py package2/ resources/ __init__.py script.py
script.py
imports packages package1
and package2
. Although the packages can be imported by any other script on the system. How should I reference resources inside, say, package1
to ensure it would work in case os.path.curdir
is arbitrary?
Upvotes: 21
Views: 20259
Reputation: 330
Use importlib_resources
.
Adding to the the example in the question, you might have something that looks like this:
/foo package1/ resources/ __init__.py resource1.txt package2/ resources/ __init__.py script.py
In Python you can use:
from importlib_resources import files
resource_path = files('package1.resources').joinpath('resource1.txt')
resource_contents = resource_path.read_text()
Upvotes: 0
Reputation: 594
A simple/safe way to do this is using the resource_filename
method from pkg_resources (which is distributed with setuptools) like so:
from pkg_resources import resource_filename
filepath = resource_filename('package1', 'resources/thefile')
Or, if you're implementing this inside package1/___init___.py
:
from pkg_resources import resource_filename
filepath = resource_filename(__name__, 'resources/thefile')
This gives you a clean solution that is also (if I'm not mistaken) zip safe.
Upvotes: 14
Reputation: 31860
You can be zip-safe and at the same time use a nice convenient API if you use twisted.python.modules.
For example, if I have a data.txt
with some text in it and and this sample.py
in one directory:
from twisted.python.modules import getModule
moduleDirectory = getModule(__name__).filePath.parent()
print repr(moduleDirectory.child("data.txt").open().read())
then importing sample
will do this:
>>> import sample
'Hello, data!\n'
>>>
If your module is in a regular directory, getModule(__name__).filePath
will be a FilePath; if it's in a zip file, it will be a ZipPath, which supports most, but not all, of the same APIs.
Upvotes: 4
Reputation: 22776
This is a bad idea, because, if your package was installed as zipped egg, then resources can be unavailable.
If you use setuptool, don't forget to add zip_safe=False to the setup.py config.
Upvotes: -1
Reputation: 4228
If you want to reference files from the foo/package1/resources
folder you would want to use the __file__
variable of the module. Inside foo/package1/__init__.py
:
from os import path
resources_dir = path.join(path.dirname(__file__), 'resources')
Upvotes: 27