在Kodi中强制Python以.py方式处理.pyo文件的技术求助
嘿,我懂你现在的困扰——折腾了Kodi源码修改,改了扩展名常量、存在性检查,甚至搞了个dummy的include.py临时凑活,但就是没法让Kodi直接把.pyo当脚本入口优先加载。咱们来一步步把这个问题捋顺,找到核心的修复点:
1. 先说说你现有代码的小问题
你之前加的检查逻辑其实方向对,但有两个容易踩的坑:
- 直接给
script加"o"的方式不够稳妥,比如遇到带多个点的文件名(比如my.plugin.py),虽然结果对,但用Kodi自带的URIUtils::ReplaceExtension会更标准。 - 最关键的是:
GetLanguageInvoker(pyoextension)大概率失败了——因为Kodi的Python调用器(Invoker)默认只认.py扩展名,你得先让它承认.pyo是合法的脚本文件。
2. 全链路修改:从扫描到执行都支持.pyo
第一步:让Kodi扫描插件时识别.pyo
别把ADDON_PYTHON_EXT直接改成*.pyo,改成同时兼容两者:
const std::string ADDON_PYTHON_EXT = "*.py|*.pyo";
这样Kodi在遍历插件文件时,会把.pyo也当成合法的Python脚本候选。
第二步:修改脚本合法性检查
你之前改的HasExtension判断,要改成同时检查.py和.pyo:
return URIUtils::HasExtension(m_strPath, ".py") || URIUtils::HasExtension(m_strPath, ".pyo");
这一步是告诉Kodi:“.pyo文件也是我要处理的Python脚本”。
第三步:调整脚本加载逻辑,优先用.pyo
把你之前加的代码改成下面这样,先试.pyo,不行再回退到.py:
// 先尝试加载对应的.pyo文件 std::string pyo_script = URIUtils::ReplaceExtension(script, ".pyo"); if (CFile::Exists(pyo_script, false)) { LanguageInvokerPtr invoker = GetLanguageInvoker(pyo_script); if (invoker) { // 确认调用器创建成功 return ExecuteAsync(pyo_script, invoker, addon, arguments); } } // 如果.pyo不存在或调用器创建失败,回退到原.py文件 if (CFile::Exists(script, false)) { LanguageInvokerPtr invoker = GetLanguageInvoker(script); return ExecuteAsync(script, invoker, addon, arguments); } // 两者都不存在才报错 CLog::Log(LOGERROR, "%s - 找不到脚本 %s 及其对应的.pyo文件", __FUNCTION__, script.c_str()); return -1;
这里用ReplaceExtension比直接拼接更可靠,而且加了invoker的有效性检查,避免创建失败还硬执行。
第四步:让Python调用器接受.pyo
找到Kodi里负责Python调用的代码(一般在xbmc/interfaces/python/CPythonInvoker.cpp这类文件里),找到检查脚本合法性的方法,比如IsValidScript,把.pyo加进去:
bool CPythonInvoker::IsValidScript(const std::string& scriptPath) { return URIUtils::HasExtension(scriptPath, ".py") || URIUtils::HasExtension(scriptPath, ".pyo"); }
这一步是核心——之前你的调用器创建失败,就是因为它不认.pyo,现在改完就能正常创建了。
3. 测试验证
编译完修改后的Kodi,测这几个场景:
- 插件所有文件都是.pyo:应该能正常启动
- 同时存在.py和.pyo:优先加载.pyo(你要的效果)
- 只有.py文件:和原来一样正常运行(兼容老逻辑)
为啥你的临时方案能 work?
那个dummy的include.py是合法的.py文件,Kodi能正常创建Python调用器,然后Python解释器本身是支持导入.pyo模块的——相当于绕开了Kodi的脚本加载逻辑,直接让Python自己处理.pyo。而咱们的源码修改是让Kodi本身就把.pyo当作合法的脚本入口,从根上解决问题。
内容的提问来源于stack exchange,提问作者Human Khoo

