我发现,这一职位同时陷入同样的问题。
My experience contradicts the experiences in the other answers.
include_package_data=True
does include the data in the
bdist! The explanation in the setuptools
documentation
lacks context and troubleshooting tips, but
include_package_data
works as advertised.
我的发言:
- Windows / Cygwin
- git version 2.21.0
- Python 3.8.1 Windows distribution
setuptools
v47.3.1
check-manifest
v0.42
Here is my how-to guide.
How-to include package data
Here is the file structure for a project I published on PyPI.
(It installs the application in __main__.py
).
├── LICENSE.md
├── MANIFEST.in
├── my_package
│ ├── __init__.py
│ ├── __main__.py
│ └── _my_data <---- folder with data
│ ├── consola.ttf <---- data file
│ └── icon.png <---- data file
├── README.md
└── setup.py
Starting point
Here is a generic starting point for the setuptools.setup()
in
setup.py
.
setuptools.setup(
...
packages=setuptools.find_packages(),
...
)
setuptools.find_packages()
includes all of my packages in the
distribution. My only package is my_package
.
The sub-folder with my data, _my_data
, is not considered a
package by Python because it does not contain an __init__.py
,
and so find_packages()
does not find it.
A solution often-cited, but incorrect, is to put an empty
__init__.py
file in the _my_data
folder.
This does make it a package, so it does include the folder
_my_data
in the distribution. But the data files inside
_my_data
are not included.
因此,将<条码>_my_data输入一个包件does not help。
解决办法是:
- the
sdist
already contains the data files
- add
include_package_data=True
to include the data files in the bdist
as well
Experiment (how to test the solution)
有三个步骤使这一试验成为重复试验:
$ rm -fr build/ dist/ my_package.egg-info/
$ check-manifest
$ python setup.py sdist bdist_wheel
I will break these down step-by-step:
- Clean out the old build:
$ rm -fr build/ dist/ my_package.egg-info/
- Run
check-manifest
to be sure MANIFEST.in
matches the
Git index of files under version control:
$ check-manifest
If MANIFEST.in
does not exist yet, create it from the Git
index of files under version control:
$ check-manifest --create
Here is the MANIFEST.in
that is created:
include *.md
recursive-include my_package *.png
recursive-include my_package *.ttf
There is no reason to manually edit this file.
As long as everything that should be under version control is
under version control (i.e., is part of the Git index),
check-manifest --create
does the right thing.
注:如果是:
- ignored in a
.gitignore
- excluded in a
.git/info/exclude
- or simply new files that have not been added to the index yet
And if any files are under version control that should not be
under version control, check-manifest
issues a warning and
specifies which files it recommends removing from the Git index.
- Build:
$ python setup.py sdist bdist_wheel
Now inspect the sdist
(source distribution) and bdist_wheel
(build distribution) to see if they include the data files.
Look at the contents of the sdist
(only the relevant lines are
shown below):
$ tar --list -f dist/my_package-0.0.1a6.tar.gz
my_package-0.0.1a6/
...
my_package-0.0.1a6/my_package/__init__.py
my_package-0.0.1a6/my_package/__main__.py
my_package-0.0.1a6/my_package/_my_data/
my_package-0.0.1a6/my_package/_my_data/consola.ttf <-- yay!
my_package-0.0.1a6/my_package/_my_data/icon.png <-- yay!
...
So the sdist
already includes the data files because they are
listed in MANIFEST.in
. There is nothing extra to do to include
the data files in the sdist
.
Look at the contents of the bdist
(it is a .zip file, parsed
with zipfile.ZipFile
):
$ python check-whl.py
my_package/__init__.py
my_package/__main__.py
my_package-0.0.1a6.dist-info/LICENSE.md
my_package-0.0.1a6.dist-info/METADATA
my_package-0.0.1a6.dist-info/WHEEL
my_package-0.0.1a6.dist-info/entry_points.txt
my_package-0.0.1a6.dist-info/top_level.txt
my_package-0.0.1a6.dist-info/RECORD
Note: you need to create your own check-whl.py
script to produce the
above output. It is just three lines:
from zipfile import ZipFile
path = "dist/my_package-0.0.1a6-py3-none-any.whl" # <-- CHANGE
print(
.join(ZipFile(path).namelist()))
如预期,<编码>bdist缺失数据文档。
The _my_data
rafter is contributed original.
What if I create a _my_data/__init__.py
? I repeat the
experiment and I find the data files are still not there! The
_my_data/
folder is included but it does not contain the data
files!
Solution
Contrary to the experience of others, this does work:
setuptools.setup(
...
packages=setuptools.find_packages(),
include_package_data=True, # <-- adds data files to bdist
...
)
现有试验:
$ rm -fr build/ dist/ my_package.egg-info/
$ check-manifest
$ python.exe setup.py sdist bdist_wheel
确保<代码>sdist 仍然有数据档案:
$ tar --list -f dist/my_package-0.0.1a6.tar.gz
my_package-0.0.1a6/
...
my_package-0.0.1a6/my_package/__init__.py
my_package-0.0.1a6/my_package/__main__.py
my_package-0.0.1a6/my_package/_my_data/
my_package-0.0.1a6/my_package/_my_data/consola.ttf <-- yay!
my_package-0.0.1a6/my_package/_my_data/icon.png <-- yay!
...
查阅<代码>bdist 的内容:
$ python check-whl.py
my_package/__init__.py
my_package/__main__.py
my_package/_my_data/consola.ttf <--- yay!
my_package/_my_data/icon.png <--- yay!
my_package-0.0.1a6.dist-info/LICENSE.md
my_package-0.0.1a6.dist-info/METADATA
my_package-0.0.1a6.dist-info/WHEEL
my_package-0.0.1a6.dist-info/entry_points.txt
my_package-0.0.1a6.dist-info/top_level.txt
my_package-0.0.1a6.dist-info/RECORD
How not to test if data files are included
I recommend troubleshooting/testing using the approach outlined
above to inspect the sdist
and bdist
.
pip install in editable mode is not a valid test
Note: pip install -e .
does not show if data files are
included in the bdist
.
The symbolic link causes the installation to behave as if the
data files are included (because they already exist locally on
the developer s computer).
After pip install my_package
, the data files are in the
virtual environment s lib/site-packages/my_package/
folder,
using the exact same file structure shown above in the list of
the whl
contents.
Publishing to TestPyPI is a slow way to test
Publishing to TestPyPI and then installing and looking in
lib/site-packages/my_packages
is a valid test, but it is too
time-consuming.