You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改Python调用代码使出错的外部脚本终止主程序?

问题:调用出错的外部脚本时,主程序未终止运行

问题背景

我们有一个Python 3面向对象程序,需要调用第三方提供的外部脚本。当前问题是:当被调用的脚本返回非零退出码(执行出错)时,主程序仍会继续运行,而非报错终止。由于无法控制第三方脚本的内容,必须在主程序中添加错误处理逻辑。

复现步骤

  • 创建两个目录MyApp和AnotherDir,文件结构如下:
    AnotherDir\scripts\brokenScript.py
    MyApp\app\main.py
    MyApp\app\second_level.py
    MyApp\app\third_level.py
    
  • 导航到两个目录的父目录
  • 执行命令:
    python MyApp\app\main.py
    

当前结果

About to run a broken script that should break on error.
command is:  python C:\path\to\AnotherDir\scripts\brokenScript.py
shell Inside broken script.  The script should break on the next line.
----------------------------------------------------------------------------
FAILED TO THROW ERROR. Done running the broken script, but it returned without breaking this calling program.  This print command should never run if the script breaks.  Instead, a graceful error message should terminate the program.

期望结果

当brokenScript.py返回非零退出码时,主程序应捕获该错误并终止运行,而非继续执行后续代码。


解决方案:修改以下代码实现错误捕获与终止

1. 修改third_level.py中的runShellCommand函数

当前subprocess.Popen启动进程后,未检查进程的退出状态码。需在读取完输出后,获取返回码并判断是否为非零,若为非零则抛出异常:

def runShellCommand(self, commandToRun):
    proc = subprocess.Popen(commandToRun, cwd=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
    while True:
        line = proc.stdout.readline()
        if line:
            thetext = line.decode('utf-8').rstrip('\r|\n')
            decodedline = self.ansi_escape.sub('', thetext)
            logString = decodedline
            print("shell", logString)
        else:
            break
    # 新增:等待进程结束并检查退出码
    proc.wait()
    exit_code = proc.returncode
    if exit_code != 0:
        raise subprocess.CalledProcessError(exit_code, commandToRun)

2. 修改third_level.py中的runScript函数

调用runShellCommand时捕获异常,输出错误信息后终止程序:

def runScript(self, relativePathToScript):
    userCallingDir = str(os.path.abspath("."))+'\\'
    userCallingDir = self.formatPathForOS(userCallingDir)
    fullyQualifiedPathToScript = userCallingDir+relativePathToScript
    fullyQualifiedPathToScript = self.formatPathForOS(fullyQualifiedPathToScript)
    if os.path.isfile(fullyQualifiedPathToScript):
        commandToRun = "python "+fullyQualifiedPathToScript
        print("command is: ",commandToRun)
        try:
            self.runShellCommand(commandToRun)
        except subprocess.CalledProcessError as e:
            print(f"shell ERROR: 脚本执行失败,退出码 {e.returncode}")
            sys.exit(1)
    else: 
        logString = "ERROR: "+fullyQualifiedPathToScript+" is not a valid path. "
        print('shell', logString)
        sys.exit(1)

3. (可选)优化second_level.py的错误处理

如果需要在业务层添加额外提示,可修改offFoundation函数捕获终止信号:

def offFoundation(self):
    tl = third_level()
    print("About to run a broken script that should break on error.")
    callScript = "\\AnotherDir\\scripts\\brokenScript.py"
    try:
        tl.runScript(callScript)
    except SystemExit:
        print("程序因外部脚本执行失败而终止")
        raise
    # 以下代码仅在脚本执行成功时运行
    print("----------------------------------------------------------------------------")
    print("脚本执行成功完成")

内容的提问来源于stack exchange,提问作者CodeMed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 13:26:12