如何读取Python包requires.txt中的依赖并评估条件表达式?
处理Python 2.7下带条件的cryptography依赖(用于RPM元数据)
针对你用python setup.py bdist_rpm构建cryptography-2.2.2时遇到的带条件表达式的依赖问题,我给你两种实用的解决方法,帮你读取并评估这些依赖,最终整理出适合添加到RPM元数据的内容:
方法一:用setuptools自带工具解析(推荐)
Python2.7的setuptools(只要版本≥36.0)自带了解析PEP 508格式条件依赖的能力,能自动根据当前环境过滤出有效的依赖。
- 先确保你的setuptools版本达标:
pip install setuptools>=36.0 - 写个简单的Python脚本解析
requires.txt:from pkg_resources import parse_requirements def get_valid_deps(requires_file_path): valid_dependencies = [] with open(requires_file_path, 'r') as f: # 逐个解析依赖项 for req in parse_requirements(f.read()): # 检查当前环境是否满足依赖的条件标记 if req.marker is None or req.marker.evaluate(): valid_dependencies.append(str(req.req)) return valid_dependencies # 替换成你的requires.txt实际路径 final_deps = get_valid_deps('/src/cryptography.egg-info/requires.txt') # 输出结果,方便后续导入RPM元数据 print("\n".join(final_deps)) - 运行这个脚本,就能直接得到当前Python2.7环境下需要的所有依赖,之后你可以把这些内容添加到RPM的
Requires字段里。
方法二:手动解析并评估条件(无额外依赖)
如果你不想升级setuptools,也可以手动解析文件内容,不过要注意只有在你完全信任requires.txt内容的情况下才用这种方法(因为用到了eval)。
- 用下面的脚本处理:
import sys import platform import os def check_marker_condition(marker_str): # 准备PEP 508标记用到的环境变量 env_vars = { 'platform_python_implementation': platform.python_implementation(), 'python_version': '.'.join(map(str, sys.version_info[:2])), 'sys_platform': sys.platform, 'os_name': os.name } # 把标记语法转成Python可执行的表达式 eval_expr = marker_str.replace('!=', '!=') \ .replace('==', '==') \ .replace('>=', '>=') \ .replace('<', '<') return eval(eval_expr, {}, env_vars) def extract_valid_deps(requires_file_path): valid_deps = [] with open(requires_file_path, 'r') as f: for line in f: line = line.strip() # 跳过空行和注释 if not line or line.startswith('#'): continue # 分离依赖和条件部分 if '[' in line and ']' in line: dep_content, marker_content = line.split('[', 1) marker_content = marker_content.rstrip(']') # 评估条件,满足就保留这个依赖 if check_marker_condition(marker_content): valid_deps.append(dep_content.strip()) else: # 没有条件的直接保留 valid_deps.append(line.strip()) return valid_deps # 替换为你的文件路径 final_deps = extract_valid_deps('/src/cryptography.egg-info/requires.txt') print("\n".join(final_deps))
整合到RPM构建流程
拿到解析后的依赖列表后,你可以把它整合到RPM构建里:
- 比如在RPM spec文件中,先运行脚本生成依赖列表,再传给
bdist_rpm:%prep # 运行脚本生成有效依赖文件 %{__python} your_script.py > resolved_deps.txt %build # 把依赖用逗号分隔传给bdist_rpm的--requires参数 python setup.py bdist_rpm --requires="$(cat resolved_deps.txt | tr '\n' ',')" - 或者直接修改
setup.py,在setup()函数里动态设置install_requires为解析后的依赖列表,这样bdist_rpm会自动把这些依赖写入RPM元数据。
内容的提问来源于stack exchange,提问作者Eddy Pronk
相关产品推荐
相关产品推荐

