在Arnie的bpps.py中集成LinearFold时持续出现KeyError 'linearfold_v'及包识别异常问题
我看了你遇到的问题,核心是Arnie没正确识别你添加的LinearFold包,而且调用参数和代码逻辑没匹配上,下面一步步给你解决:
1. 先补全调用时的关键参数:linear=True
你在bpps.py里把LinearFold的处理逻辑放在了if linear:的条件块里,但你测试时调用bpps(seq, package="linearfold_v")没传linear=True!这就导致代码完全走不到你写的LinearFold分支,而是会走原来的默认逻辑,自然找不到linearfold_v这个包。
修改你的测试代码:
# test_bpps.py from arnie.bpps import bpps seq = "GGCGGAUGCAUGGAGCUAAUGGCUGUAGCUCA" # 必须加上linear=True,才能触发你写的LinearFold处理逻辑 result = bpps(seq, package="linearfold_v", linear=True) print(result)
2. 修复bpps.py里的包判断逻辑(避免走"Unexpected package"分支)
你说debug输出显示DEBUG: Unexpected package linearfold_v for linear processing!,说明package in ["linearfold_v", ...]的判断没命中。先检查bpps.py开头的代码:
package = package.lower()
如果你调用时传的包名有大小写混写,lower()后会统一为小写,你可以把判断逻辑改成用之前拆分的pkg和version来判断,更贴合原代码风格,也避免硬编码完整包名:
if linear: print(f"DEBUG: Linear is set to True, checking package: {package}") # 用拆分后的pkg和version判断,更灵活 if pkg == "linearfold": if version in ["v", "c", "e"]: print(f"DEBUG: Calling bpps_linearfold with {package}") return bpps_linearfold(sequence) else: print(f"DEBUG: Unknown LinearFold type: {version}") elif pkg == "linearpartition": if version in ["v", "c", "e"]: print(f"DEBUG: Calling bpps_linearpartition with {package}") return bpps_linearpartition(sequence, tmp_file) else: print(f"DEBUG: Unknown LinearPartition type: {version}") else: print(f"DEBUG: Unexpected linear package {package}!")
3. 让Arnie正确加载linearfold_v的路径(解决load_package_locations()看不到它的问题)
你的arnie_config.txt里加了linearfold_v的路径,但load_package_locations()没输出它,大概率是因为Arnie的load_package_locations()只会加载package_options.py里定义的包对应的路径,或者你的package_options.py映射格式不对。
先修正package_options.py里的LinearFold映射,加上可执行文件的对应关系:
package_options = { # ... 保留原来的其他包 ... 'linearfold_v': {'package': 'linearfold', 'type': 'v', 'executable': 'linearfold_v'}, 'linearfold_c': {'package': 'linearfold', 'type': 'c', 'executable': 'linearfold_c'}, 'linearfold_e': {'package': 'linearfold', 'type': 'e', 'executable': 'linearfold_e'}, 'linearpartition_v': {'package': 'linearpartition', 'type': 'v', 'executable': 'linearpartition_v'}, # ... 其他LinearPartition包 ... }
然后修改bpps_linearfold函数,不要硬编码路径,而是从package_locs里读取(符合Arnie的规范):
def bpps_linearfold(sequence, package): """Run LinearFold on a sequence and return base-pairing probabilities.""" import subprocess # 从package_locs获取路径,避免硬编码 linearfold_path = package_locs.get(package) if not linearfold_path: raise RuntimeError(f"Path for {package} not found in arnie_config.txt!") command = [linearfold_path, "--prob", sequence] process = subprocess.run(command, text=True, capture_output=True) if process.returncode != 0: raise RuntimeError(f"LinearFold failed: {process.stderr}") return process.stdout
4. 确认Arnie读取的是正确的arnie_config.txt
有时候Arnie会读取当前目录的arnie_config.txt,而不是~/.arnie_config.txt,你可以手动指定config路径测试:
import arnie.utils # 直接指定config文件路径 package_locs = arnie.utils.load_package_locations(config_path="/home/vboxuser/.arnie_config.txt") print(package_locs)
如果这里能看到linearfold_v的路径,说明config加载正常了。如果看不到,检查arnie_config.txt的格式:冒号后必须加空格(比如linearfold_v: /home/...,不能是linearfold_v:/home/...)。
5. 彻底修复:给linearfold加专属分支(无需依赖linear=True)
如果你不想每次调用都传linear=True,可以在bpps.py里给linearfold加一个专属分支,直接调用你的自定义函数:
# 在bpps.py里,处理完pkg和version的拆分后,添加以下代码 if pkg == "linearfold": print(f"DEBUG: Processing LinearFold package: {package}") return bpps_linearfold(sequence, package) elif pkg == "linearpartition": return bpps_linearpartition(sequence, tmp_file, package) # ... 保留原来的vienna、contrafold等分支 ...
这样即使没传linear=True,只要package是linearfold_v,代码也能正确处理。
最后验证步骤
- 重启Python解释器(避免缓存旧的模块)
- 运行测试代码,检查是否还出现KeyError
- 如果仍有问题,打印
package_locs和package_options确认:
import arnie.utils from arnie.package_options import package_options print("Package locations:", arnie.utils.load_package_locations()) print("Package options:", package_options)
如果package_locs里没有linearfold_v,说明你的arnie_config.txt路径不对或格式错误。
备注:内容来源于stack exchange,提问作者Hugh Redford

