我发现这个问题有很多变化,但似乎没有一个能解决我的确切情况
- 项目的 Python 代码包含在单个文件中
- 安装中必须包含必需的数据目录
我正在尝试创建以下 Python 项目的pip
可安装版本,其中该项目由单个 Python 脚本myscript
,以及两个不同的数据目录data
和test_data
组成。data
包含运行时由myscript.py
获取的必需数据文件:
myscript
|
├── myscript
│ ├── data
│ ├── __init__.py
│ ├── myscript.py
│ └── test_data
├── LICENSE
├── README.md
└── setup.py
我已经看到了在setup.py
中使用py_modules
来解决类似问题的建议,但这似乎不允许在安装时包含数据目录pip
,而且我找不到似乎涵盖此特定情况的文档。
我还看到建议让用户只对存储库进行git clone
而不是使用pip
,但提供一种pip
安装所有依赖项的方法似乎是一种可用性优势,同时以依赖于操作系统的方式正确将脚本添加到 PATH。
这看起来像一个非常标准的Python包。为了重现您的情况,我有以下布局:
$ find * -type f
LICENSE
myscript/myscript.py
myscript/data/data_file_1
myscript/test_data/test_data_file_1
myscript/__init__.py
README.md
setup.cfg
setup.py
要包含数据目录,您可以在setup.cfg
文件中使用package_data
选项(它正在慢慢取代setup.py
作为构建 Python 包的标准方法(。
我们只需要一个存根setup.py
:
from setuptools import setup
setup()
其他一切都在setup.cfg
:
[metadata]
name = myscript
version = 1.0
description = An example for glarue
long_description = file: README.md
long_description_content_type = text/markdown
url = https://github.com/larsks/so-example-glarue
author = Lars Kellogg-Stedman
author_email = lars@oddbit.com
[options]
packages = find:
[options.package_data]
myscript = data/*, test_data/*
[options.entry_points]
console_scripts =
myscript = myscript.myscript:main
关键部分是options.package_data"部分,对于每个包,它列出了应作为包一部分包含的 glob 模式。
如果我们从这里构建一个源代码发行版:
$ python setup.py sdist
running sdist
...
Creating tar archive
removing 'myscript-1.0' (and everything under it)
我们可以看到数据文件包含在存档中:
$ tar tf dist/myscript-1.0.tar.gz
myscript-1.0/
myscript-1.0/PKG-INFO
myscript-1.0/README.md
myscript-1.0/myscript/
myscript-1.0/myscript/__init__.py
myscript-1.0/myscript/data/
myscript-1.0/myscript/data/data_file_1
myscript-1.0/myscript/myscript.py
myscript-1.0/myscript/test_data/
myscript-1.0/myscript/test_data/test_data_file_1
myscript-1.0/myscript.egg-info/
myscript-1.0/myscript.egg-info/PKG-INFO
myscript-1.0/myscript.egg-info/SOURCES.txt
myscript-1.0/myscript.egg-info/dependency_links.txt
myscript-1.0/myscript.egg-info/entry_points.txt
myscript-1.0/myscript.egg-info/top_level.txt
myscript-1.0/setup.cfg
myscript-1.0/setup.py
如果您使用bdist
构建二进制发行版,情况也是如此。
您可以在 https://github.com/larsks/so-example-glarue 在线找到整个示例。
我认为您缺少MANIFEST.in
文件
请看以下小项目:
目录结构
./MANIFEST.in
./mini/data/f1.txt
./mini/__init__.py
./mini/mini.py
./mini/test_data/f1.txt
./README.md
./setup.py
setup.py
from setuptools import setup
setup(name="mini",
version="0.0.1",
description="one file pip installable mod",
long_description="long description",
long_description_content_type="text/x-rst",
classifiers=[
"Development Status :: 3 - Alpha",
],
keywords="sample",
url="https://github.com/demo",
author="me",
author_email="me@my.email.com",
license="MIT",
packages=["mini"],
scripts=[],
entry_points={
"console_scripts": [
"mini = mini.mini:main",
]
},
install_requires=[],
extras_require={},
python_requires=">=3.4",
setup_requires=[],
tests_require=[],
zip_safe=False,
include_package_data=True,
)
MANIFEST.in
include README.md
recursive-include mini/data/ *
recursive-include mini/test_data/ *
迷你/迷你.py
#!/usr/bin/env python
import os
MYPATH = os.path.realpath(os.path.dirname(__file__))
DATA_PATH = os.path.join(MYPATH, "data")
TEST_DATA_PATH = os.path.join(MYPATH, "test_data")
def main():
print("I am the miniscript")
with open(os.path.join(DATA_PATH, "f1.txt")) as fin:
print("DATA FILE", fin.read())
with open(os.path.join(TEST_DATA_PATH, "f1.txt")) as fin:
print("TEST DATA FILE", fin.read())
main()
试用:
python -m setup sdist
tar tvfz dist/mini-0.0.1.tar.gz