I don’t understand how exactly pkg_resource.resource_filename() work and what are its parameters. I searched a lot on web but their official documentation does not cover it well. Can someone explain it?
Advertisement
Answer
Here are a few examples. I have wheel 0.24 installed in an old environment:
pkg_resources.resource_filename('spamalot', "wheel/__init__.py") ImportError: No module named spamalot
The first argument has to be importable. The second argument should be a relative, /-separated path, including on systems that use to separate paths.
In [27]: pkg_resources.resource_filename('distutils', "wheel/__init__.py") Out[27]: '/opt/pyenv/lib64/python2.7/distutils/wheel/__init__.py'
If it is importable, you will get a path inside the imported name. In this case it doesn’t matter whether the file exists.
In [28]: pkg_resources.resource_filename(pkg_resources.Requirement.parse('wheel>0.23.0'), "core.py") Out[28]: '/opt/pyenv/lib/python2.7/site-packages/core.py'
You can pass a requirement, and it will check if you actually have it installed. Now the path is relative to the install directory and not the wheel
package.
In [29]: pkg_resources.resource_filename(pkg_resources.Requirement.parse('wheel>0.27.0'), "core.py") VersionConflict: (wheel 0.24.0 (/opt/pyenv/lib/python2.7/site-packages), Requirement.parse('wheel>0.27.0'))
If the requirement is not installed it will complain.
One reason the Requirement
feature exists is because it’s possible to have eggs for multiple versions of the same package on the path, and pkg_resources
will add the requested version, but this feature is not used very much any more.
These examples are pretty simple, but resource_filename
will also work if your resources are inside a .zip
file or any other supported import location (it is possible to hook Python’s import system so that imports come from anywhere – sqlite databases, the network, …, and resource_filename should be able to work with these if the right hooks are installed.)