如何将setup.py的绝对路径纳入PKG-INFO元数据?
解决思路与实现方案
哈,我懂你的痛点——每次改完资源文件都要跑python setup.py install才能生效,想通过把项目路径塞进PKG-INFO里,动态生成资源文件夹的路径对吧?下面给你几个可行的方案:
1. 直接将项目路径写入PKG-INFO(符合你的需求)
你可以在setup.py里先获取自身的绝对路径,再把项目根目录作为自定义元数据写入PKG-INFO。这样安装后就能从元数据里读取路径,生成你需要的资源文件夹路径。
示例代码(setup.py)
import os from setuptools import setup, find_packages # 获取setup.py的绝对路径,推导项目根目录 setup_file_path = os.path.abspath(__file__) project_root_dir = os.path.dirname(setup_file_path) setup( name='myproject', version='0.1', packages=find_packages(), # 添加自定义元数据,将项目根目录写入PKG-INFO metadata={ 'other': { 'X-Project-Root': project_root_dir, } }, # 同时保留package_data配置(可选) package_data={ 'myproject': ['resources/**/*'], }, )
读取PKG-INFO中的路径
安装完成后,你可以用pkg_resources模块读取这个自定义元数据:
import os import pkg_resources def get_project_root(): try: # 获取当前包的分发信息 dist = pkg_resources.get_distribution('myproject') # 读取自定义的项目根目录字段 return dist.get_metadata('X-Project-Root') except pkg_resources.DistributionNotFound: # 如果包未安装(开发阶段),从当前文件路径推导根目录 return os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 生成资源文件夹路径 resources_dir = os.path.join(get_project_root(), 'myproject', 'resources')
2. 更优雅的替代方案:无需硬编码路径
其实你完全不用把路径写入PKG-INFO,通过Python自带的工具就能动态获取资源,还能避免路径硬编码带来的移植性问题,而且开发阶段修改资源后不用重新安装!
方案A:用pip install -e .做可编辑安装 + pkg_resources
首先在开发阶段执行:
pip install -e .
这样包会以“可编辑”模式安装,修改资源文件后立即生效。
然后在代码中读取资源:
import pkg_resources # 获取资源文件的绝对路径 resource_path = pkg_resources.resource_filename('myproject', 'resources/myfile.txt') # 直接读取资源内容 with pkg_resources.resource_stream('myproject', 'resources/myfile.txt') as f: content = f.read().decode('utf-8')
方案B:Python 3.7+ 用标准库importlib.resources
这是更推荐的标准库方案,无需依赖setuptools的pkg_resources:
from importlib.resources import files, as_file # 获取资源文件并读取内容 with as_file(files('myproject.resources') / 'myfile.txt') as resource_path: with open(resource_path, 'r', encoding='utf-8') as f: content = f.read()
同样配合pip install -e .,修改资源后无需重新安装。
内容的提问来源于stack exchange,提问作者Rilwan
相关产品推荐
相关产品推荐

