What would be a cross-platform way of shipping data_files
with setup.py
(compatible with pip
)?
From the official documentation, one needs to write:
setup(...,
data_files=[('bitmaps', ['bm/b1.gif', 'bm/b2.gif']),
('config', ['cfg/data.cfg']),
('/etc/init.d', ['init-script'])]
)
and 'bitmaps'
, etc. are the sub-directories where those files should go (relative to sys.prefix
).
However, this is sub-optimal for cross-platform installations where the standard sub-dir will depend on the system. Additionally, installing the package in developer mode will not place the files where they will later be after the installation, making this process of finding/using resources ultimately hard / annoying to debug.
I have looked into appdirs
, but it seems difficult to make it work properly during installation, e.g. if using the user directory for data this gets actually tied to my development environment.
The reason I am asking this is because I have a small Python package that implements a simple GUI and I would like to ship an icon with it.
For the record, I am OK with processing setup.py
with setuptools
.
As suggested in the comments, for bundling resource files, I'd rather use package_data and place the files under some package dir. Example:
project
├── pkg1
│ ├── __init__.py
│ └── icons
│ └── image.png
└── pkg2
└── __init__.py
Packaging in the setup.py
script:
from setuptools import setup
setup(
...
package_data={'pkg1': ['icons/image.png']},
)
Python 3.7 introduced importlib.resources
which replaces the old pkg_resources
functionality and offers a modern resource machinery that utilizes pathlib
:
filepath = importlib_resources.path('pkg1', 'icons/image.png')
For Python 3.6 and older, there's a backport named importlib_resources
. The version-agnostic example is thus:
import sys
if sys.version_info >= (3, 7):
from importlib import resources as importlib_resources
else:
import importlib_resources
filepath = importlib_resources.path('pkg1', 'icons/image.png')
Use importlib_resources
instead of pkg_resources
where possible.
To reference the resource files in code, use pkg_resources
:
import pkg_resources
filepath = pkg_resources.resource_filename('pkg1', 'icons/image.png')
The cross-platform support is thus handled by pkg_resources
. Refer to ResourceManager
API for available resource access functions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With