Pythonの自作パッケージにリソースファイルを含めるには

Pythonソースコード以外にテキストや画像など任意のファイルをパッケージに含めて、Pythonコードから参照する方法のメモです。

手順の概要

  1. setup.pyinclude_package_data = True と記載
  2. パッケージに含めたいファイル名を MANIFEST.in に記載
  3. Pythonコードからは pkgutil.get_data("sample", "data.txt") で参照

ソースコード

$ find . -type f
./requirements.txt
./sample/data.txt
./sample/__init__.py
./sample/main.py
./setup.py
./MANIFEST.in

requirements.txt

空ファイル

sample/data.txt

適当なリソースファイル

Hello

sample/__init__.py

空ファイル

sample/main.py

リソースファイルを参照するPythonコードのサンプル

import pkgutil

def main():
    print(pkgutil.get_data("sample", "data.txt"))
    # bytes型でファイルの中身を取得できる

setup.py

include_package_data = True が必要です。

from setuptools import setup, find_packages

with open('requirements.txt') as requirements_file:
    install_requirements = requirements_file.read().splitlines()

setup(
    name        = "sample",
    version     = "0.0.0",
    description = "A sample tool",
    author      = "suzuki-navi",
    include_package_data = True, # これが必要!
    packages    = find_packages(),
    install_requires = install_requirements,
    entry_points = {
        "console_scripts": [
            "sample = sample.main:main",
        ]
    },
)

MANIFEST.in

リソースファイルとしてパッケージに含めたいファイルを書きます。

include requirements.txt
include sample/*.txt

recursive-includeディレクトリの中を再帰的に探すこともできるようです。

Including files in source distributions with MANIFEST.in — Python Packaging User Guide

動かしてみる

その場で実行

$ pip install -e .

$ sample
b'Hello\n'

パッケージ作成

$ python setup.py sdist

tar.gzファイルに sample-0.0.0/sample/data.txt が含まれます。

$ tar tf dist/sample-0.0.0.tar.gz
sample-0.0.0/
sample-0.0.0/MANIFEST.in
sample-0.0.0/PKG-INFO
sample-0.0.0/requirements.txt
sample-0.0.0/sample/
sample-0.0.0/sample/__init__.py
sample-0.0.0/sample/data.txt
sample-0.0.0/sample/main.py
sample-0.0.0/sample.egg-info/
sample-0.0.0/sample.egg-info/PKG-INFO
sample-0.0.0/sample.egg-info/SOURCES.txt
sample-0.0.0/sample.egg-info/dependency_links.txt
sample-0.0.0/sample.egg-info/entry_points.txt
sample-0.0.0/sample.egg-info/top_level.txt
sample-0.0.0/setup.cfg
sample-0.0.0/setup.py

インストールして実行

$ pip install dist/sample-0.0.0.tar.gz
$ sample
b'Hello\n'

インストール先に sample/data.txt が含まれていることがわかります。

$ ls ~/.local/lib/python3.8/site-packages/sample/
data.txt  __init__.py  main.py  __pycache__