在 setup.py 构建中包含来自项目根目录的 python 文件
including python file from project root in setup.py build
我试图在 运行
时创建的 build/lib 目录中包含一个 python 文件
python setup.py install
特别是,我想包含一个简单的配置文件 ('definitions.py'),它定义了一个 ROOT_DIR 变量,然后由子包使用。 'definitions.py' 文件包含:
import os
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
我的目标是让每个子包中的配置文件 ('config.py') 调用 ROOT_DIR 来构建自己的绝对路径:
from definitions import ROOT_DIR
PACKAGE_DIR = os.path.join(ROOT_DIR, 'package1/')
这个想法来自这个 Whosebug 答案:。
但是,当 运行 'setup.py install' 时,这个 'definitions.py' 文件永远不会出现在构建目录中。
项目目录结构如下:
project
|
├── setup.py
|
├── definitions.py
|
├── package1
| ├── __init__.py
| ├── config.py
| └── ...
|
├── package2
| ├── __init__.py
| └── ...
└── ...
我的多次尝试都失败了(尝试,例如 中提供的建议)。据我所知,这是因为 definitions.py 位于我的项目结构的顶层(缺少 __init__.py 文件)。
我试过了:
1) ...在 setuptools.setup() 中使用 'package-data' 变量
package_data={'package': ['./definitions.py']}
但 definitions.py 没有出现在构建
中(我认为是因为 definitions.py 不在具有 __init__.py?)。
2) ...使用 MANIFEST.in 文件,但这也不起作用
(我认为是因为 MANIFEST 不适用于 .py 文件?)
我的问题:
有没有办法在构建目录中包含 definitions.py?
或者,有没有更好的方法可以访问从顶级目录构建的多个子包的绝对路径?
如果您正在寻找一种方法来访问已安装模块中的非 python 数据文件,就像您链接的问题一样(顶级包中的配置文件应该可以访问在子包中),使用 pkg_resources
机制而不是发明自定义路径解析。示例项目结构:
project
├── setup.py
└── root
├── __init__.py
├── config.txt
├── sub1
│ └── __init__.py
└── sub2
└── __init__.py
setup.py
:
from setuptools import setup
setup(
name='myproj',
...,
packages=['root', 'root.sub1', 'root.sub2'], # or setuptools.find_packages()
package_data={'root': ['config.txt']}
)
更新:
正如 wim in the comments, there's now a backport for importlib.resources
(which is only available in Python 3.7 and onwards) - importlib_resources
所指出的,它提供了一种利用 pathlib
:
的现代资源机器
# access the filepath
importlib_resources.path('root', 'config.txt')
# access the contents as string
importlib_resources.read_text('root', 'config.txt')
# access the contents as file-like object
importlib_resources.open_binary('root', 'config.txt')
原回答
使用 pkg_resources
,您可以从包的任何位置访问 root/config.txt
,而无需执行任何路径解析:
import pkg_resources
# access the filepath:
filepath = pkg_resources.resource_filename('root', 'config.txt')
# access the contents as string:
contents = pkg_resources.resource_string('root', 'config.txt')
# access the contents as file-like object:
contents = pkg_resources.resource_stream('root', 'config.txt')
等等
我试图在 运行
时创建的 build/lib 目录中包含一个 python 文件python setup.py install
特别是,我想包含一个简单的配置文件 ('definitions.py'),它定义了一个 ROOT_DIR 变量,然后由子包使用。 'definitions.py' 文件包含:
import os
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
我的目标是让每个子包中的配置文件 ('config.py') 调用 ROOT_DIR 来构建自己的绝对路径:
from definitions import ROOT_DIR
PACKAGE_DIR = os.path.join(ROOT_DIR, 'package1/')
这个想法来自这个 Whosebug 答案:。
但是,当 运行 'setup.py install' 时,这个 'definitions.py' 文件永远不会出现在构建目录中。
项目目录结构如下:
project | ├── setup.py | ├── definitions.py | ├── package1 | ├── __init__.py | ├── config.py | └── ... | ├── package2 | ├── __init__.py | └── ... └── ...
我的多次尝试都失败了(尝试,例如 中提供的建议)。据我所知,这是因为 definitions.py 位于我的项目结构的顶层(缺少 __init__.py 文件)。
我试过了:
1) ...在 setuptools.setup() 中使用 'package-data' 变量
package_data={'package': ['./definitions.py']}
但 definitions.py 没有出现在构建
中(我认为是因为 definitions.py 不在具有 __init__.py?)。
2) ...使用 MANIFEST.in 文件,但这也不起作用
(我认为是因为 MANIFEST 不适用于 .py 文件?)
我的问题:
有没有办法在构建目录中包含 definitions.py?
或者,有没有更好的方法可以访问从顶级目录构建的多个子包的绝对路径?
如果您正在寻找一种方法来访问已安装模块中的非 python 数据文件,就像您链接的问题一样(顶级包中的配置文件应该可以访问在子包中),使用 pkg_resources
机制而不是发明自定义路径解析。示例项目结构:
project
├── setup.py
└── root
├── __init__.py
├── config.txt
├── sub1
│ └── __init__.py
└── sub2
└── __init__.py
setup.py
:
from setuptools import setup
setup(
name='myproj',
...,
packages=['root', 'root.sub1', 'root.sub2'], # or setuptools.find_packages()
package_data={'root': ['config.txt']}
)
更新:
正如 wim in the comments, there's now a backport for importlib.resources
(which is only available in Python 3.7 and onwards) - importlib_resources
所指出的,它提供了一种利用 pathlib
:
# access the filepath
importlib_resources.path('root', 'config.txt')
# access the contents as string
importlib_resources.read_text('root', 'config.txt')
# access the contents as file-like object
importlib_resources.open_binary('root', 'config.txt')
原回答
使用 pkg_resources
,您可以从包的任何位置访问 root/config.txt
,而无需执行任何路径解析:
import pkg_resources
# access the filepath:
filepath = pkg_resources.resource_filename('root', 'config.txt')
# access the contents as string:
contents = pkg_resources.resource_string('root', 'config.txt')
# access the contents as file-like object:
contents = pkg_resources.resource_stream('root', 'config.txt')
等等