setuptools
has three different ways to specify data files that should be packages together with your project, Manifest.in
, data_files
, and package_data
. For config files that are under your source tree, package_data
is usually the easiest to use.
Given a very small sample project that looks like this:
.
├───setup.py
└───tmp
├───__init__.py
└───keys.json
You'd need a setup.py
file with at least this configuration to package all code and .json
files under tmp
:
from setuptools import setup
setup(
name="tmp",
version="0.1.0",
packages=["tmp"],
package_data={"tmp": ["*.json"]},
)
The keys.json
file only contains {"key": "foo"}
.
The safest way to parse packaged config files from within your package is to use importlib.resources
to access it, in particular its path
function (if you are stuck on python 3.7 or older, importlib_resources
is an equivalent pip-installable backport):
tmp/__init__.py
from importlib import resources
import json
def print_keys():
with resources.path("tmp", "keys.json") as foo_path:
print(json.load(foo_path.open()))
Once I install this package with pip install -e .
, I can run:
>>> import tmp
>>> tmp.print_keys()
{'key': 'foo'}
If you plan to work with python packaging for a while, consider using a more modern build-backend than setuptools, such as poetry or flit. They make the experience a lot more bearable.