损坏的脚本无法中断调用程序

问题描述 投票:0回答:1

为了使损坏的脚本停止调用它的程序,需要更改以下代码中的哪些具体语法?

问题:

面向对象的Python 3程序需要运行外部脚本。问题是,当程序调用中断的脚本时,Python 程序只是继续运行,而不是因错误消息而停止。

这些脚本是由我们无法控制的第三方提供的,因此面向对象的python 3程序需要在调用的脚本中断时进行错误处理,而我们无法控制调用的脚本的内容。

重现问题的步骤:

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

    AnotherDir\scripts rokenScript.py
    MyApp pp\main.py
    MyApp pp\second_level.py
    MyApp pphird_level.py

  2. 将命令行导航到 AnotherDir 和 MyApp 的父目录

  3. 运行以下命令来重现问题:

    python MyApp pp\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
python python-3.x shell popen
1个回答
0
投票

对于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 中的其他所有内容都可以保持不变,整个程序将按预期运行。

© www.soinside.com 2019 - 2024. All rights reserved.