Swift中通过PythonKit调用带命令行参数Python脚本及防崩溃方法
PythonKit调用带命令行参数脚本及崩溃问题解决方案
1. 带命令行参数脚本的正确调用方式
绝大多数Python脚本的main()函数默认从sys.argv列表读取命令行参数,而非直接接收函数入参,直接传入"-v"的写法不符合脚本的参数读取逻辑,自然无法正常运行。
正确操作是在调用脚本前手动构造sys.argv列表,完全模拟终端运行时的参数环境:
let sys = Python.import("sys") sys.path.append("/Path/To/Script/Directory/") // sys.argv第一个元素固定为脚本名称,和终端运行规则一致 sys.argv = ["my_script", "-v"] let example = Python.import("my_script") example.main()
如果你的脚本main函数本身设计为接收argv列表作为入参,传入参数时要传递完整的列表参数,而非单个字符串:
example.main(["my_script", "-v"])
额外提醒:你贴出的代码里路径、模块名使用了中文全角引号“”,如果实际代码存在这个问题会直接导致模块加载失败,需要替换为英文半角引号""。
2. 规避sys.exit()触发崩溃的方案
崩溃的核心原因是Python中sys.exit()会抛出SystemExit异常,PythonKit内部用try!强制处理调用结果,未被捕获的Python异常会直接触发Swift层面的崩溃。不管是无参打印帮助信息、还是传-v打印版本号,只要脚本逻辑里调用了sys.exit()就会触发这个问题,有两种常用解决方式:
- 方式一:在Swift层捕获Python异常
调用main方法时用do-catch捕获异常,针对性处理SystemExit类型的退出事件,既可以拿到退出码、输出内容,也能避免崩溃:let sys = Python.import("sys") sys.path.append("/Path/To/Script/Directory/") sys.argv = ["my_script"] let example = Python.import("my_script") do { try example.main() } catch { let pyErr = error as! PythonError let builtins = Python.import("builtins") if pyErr.exception.type.isInstance(builtins.SystemExit) { let exitCode = pyErr.exception.args[0] print("脚本执行完成,退出码:\(exitCode)") } } - 方式二:提前拦截sys.exit调用
如果不需要获取脚本退出码,可以在导入脚本前重写sys.exit方法,替换为空逻辑,从根源阻止异常抛出:let sys = Python.import("sys") // 重写sys.exit为空实现 sys.exit = Python.PythonFunction { _ in return Python.None } sys.path.append("/Path/To/Script/Directory/") let example = Python.import("my_script") // 后续调用main不会因为sys.exit崩溃 example.main()
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

