python-3.x 中断的脚本无法中断调用程序

5jvtdoz2  于 2023-10-21  发布在  Python
关注(0)|答案(1)|浏览(175)

下面的代码中需要修改什么特定的语法,才能使损坏的脚本停止调用它的程序?

问题:

一个面向对象的Python 3程序需要运行外部脚本。问题是,当程序调用中断的脚本时,Python程序只是继续运行,而不是停止并显示错误消息。
脚本是由我们无法控制的第三方提供的,因此当调用脚本中断时,面向对象的Python 3程序需要进行错误处理,我们无法控制调用脚本的内容。

重现问题的步骤:

1.创建两个目录,并将以下4个文件放在这两个目录中。一个目录名为MyApp,另一个目录名为AnotherDir。文件结构应如下所示:

AnotherDir\scripts\brokenScript.py
 MyApp\app\main.py
 MyApp\app\second_level.py
 MyApp\app\third_level.py

1.将命令行导航到AnotherDir和MyApp的父目录
1.运行以下命令重现问题:

python MyApp\app\main.py

我们正在Windows上开发这个,但它的目的是与操作系统无关。

问题结果:

问题是结果看起来像:

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脚本的非零退出代码应该会导致调用程序停止而不是继续运行。

重现问题的代码:

100%重现此错误的最低限度代码如下:
AnotherDir\scripts\brokenScript.py包含:

import sys

print("Inside broken script.  The script should break on the next line. ")
sys.exit(1)

MyApp\main.py包含:

from second_level import second_level
import sys

def runCommands():
  wfsys = second_level()
  wfsys.offFoundation()
  print("--------------------------------------")
  sys.exit(0)

runCommands()

MyApp\second_level.py包含:

from third_level import third_level

class second_level:

  def __init__(self):  
    pass

  def offFoundation(self):
    tl = third_level()
    print("About to run a broken script that should break on error.")
    callScript = "\\AnotherDir\\scripts\\brokenScript.py"
    tl.runScript(callScript)
    print("----------------------------------------------------------------------------")
    print("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.")

MyApp\third_level.py包含:

import subprocess
import re
import sys 
import os
import platform

class third_level:

  def __init__(self):  
    pass
 
  ansi_escape = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]')

  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

  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)
      self.runShellCommand(commandToRun)
    else: 
      logString = "ERROR: "+fullyQualifiedPathToScript+" is not a valid path. "
      print('shell', logString)
      sys.exit(1)

  def formatPathForOS(self, input):
    if platform.system() == "Windows":
      input = input.replace('/','\\')   
    else:
      input = input.replace('\\','/')  
      input = input.replace('//','/')
    if input.endswith('/n'):  
      input = input[:-2] + '\n'
    return input
j7dteeu8

j7dteeu81#

对于OP中给出的代码,解决方案是添加以下三行:

stdoutdata, stderrdata = proc.communicate()
if proc.returncode != 0:
  print("ERR4R: The script that was called returned a non-zero return code: ", proc.returncode)

添加了这三行的函数的完整代码如下所示:

def runShellCommand(self, commandToRun):
  proc = subprocess.Popen( commandToRun,cwd=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
  stdoutdata, stderrdata = proc.communicate()
  if proc.returncode != 0:
    print("ERR4R: The script that was called returned a non-zero return code: ", proc.returncode)
  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

OP中的其他一切都可以保持不变,整个程序将按预期工作。

相关问题