【问题标题】:Calling a subprocess in Python 3.4 and handling errors if a command is invalid?在 Python 3.4 中调用子进程并在命令无效时处理错误?
【发布时间】:2014-09-20 22:40:21
【问题描述】:

我正在尝试在 Python 3.4 中执行外部进程。当我的“命令”错误时,程序就会崩溃。如何优雅地处理错误并恢复?

    # Call a system process
    try:
        pipe = subprocess.Popen(command,
                                stdout=subprocess.PIPE)
    except (OSError,
            subprocess.CalledProcessError) as error:
        print("Failed to execute command")
        print(command)
        print("Error: " + error.output)

    while True:
        output = pipe.stdout.readline()
        if not output:
            print("Finished...")
            break

        output = output.decode()
        output = output.strip("\r")
        output = output.strip("\n")
        print(output)

当我调用无效命令时。我遇到这样的崩溃:

C:\SDKs\Python34\python.exe C:\Users\user\Documents\GitHub\PyQtApps\QtDeploy\src\main.py
Traceback (most recent call last):
Executing:  windeployqt.exe  C:\Users\user\Documents\GitHub\SpaCentralSoftBin\GUIController.exe
  File "C:\Users\user\Documents\GitHub\PyQtApps\QtDeploy\src\forms\maindialog.py", line 81, in execute_windeployqt
Failed to execute command
    stdout=subprocess.PIPE)
windeployqt.exe  C:\Users\user\Documents\GitHub\SpaCentralSoftBin\GUIController.exe
  File "C:\SDKs\Python34\lib\subprocess.py", line 858, in __init__
    restore_signals, start_new_session)
  File "C:\SDKs\Python34\lib\subprocess.py", line 1111, in _execute_child
    startupinfo)
FileNotFoundError: [WinError 2] The system cannot find the file specified

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\user\Documents\GitHub\PyQtApps\QtDeploy\src\forms\maindialog.py", line 159, in on_buttonBox_clicked
    self.execute_windeployqt()
  File "C:\Users\user\Documents\GitHub\PyQtApps\QtDeploy\src\forms\maindialog.py", line 86, in execute_windeployqt
    print("Error: " + error.output)
AttributeError: 'FileNotFoundError' object has no attribute 'output'

【问题讨论】:

  • 不相关:您可以使用 for 循环逐行读取输出:for line in p.stdout: sys.stdout.buffer.write(line)# + do something else with the line。为避免手动解码字节,您可以指定universal_newlines=True(它还将'\r''\r\n' 转换为'\n'),然后您可以将其读取为:for line in p.stdout: print(line, end='')。要将 stderr(可能出现错误的地方)与 stdout 合并,请指定 stderr=subprocess.STDOUT
  • @J.F.Sebastian 谢谢!这很有用。目前,我单独阅读 stderr 以显示进程是否返回错误。你知道如何在不读取缓冲区的情况下检查是否有错误(就像在 for 循环中那样)。我需要设置一个布尔变量。

标签: python python-3.x subprocess


【解决方案1】:

更大的问题是打印错误消息并不能“处理”任何有意义的“处理”意义上的错误(尽管许多人认为它可以)。

根据需要记录错误消息,然后退出程序。在少数情况下您可以处理错误,例如,如果无法读取配置文件,请查看是否可以读取全局配置文件,或者可以将 KeyboardInterrupt 传递给正在读取命令的主循环。

在您的示例中,如果您没有在 except 块中出错,output = pipe.stdout... 将产生:

NameError: name 'pipe' is not defined

如果你发现了这一点,那么恢复你的代码预期的状态仍然没有任何意义。你还将把你确实得到的回溯移动到一个没有错误的地方。

适合您的情况的成语是

except SomeError:
    log what you want
    raise

一个空的raise 重新引发最后一个异常,该异常将向上传播,形成一个完整的堆栈跟踪,这将使您更好地了解故障所在。如果您不这样做,您将丢弃有用的信息。

【讨论】:

  • 我的程序只是 PyQt 中用于控制台应用程序的简单 GUI。一个简单的消息框就足以通知用户选择不同的参数。根据之前发帖者的建议,无论如何,我发现我的代码存在严重缺陷。感谢您的意见。老实说,我有点困惑,我需要考虑一下。现在我有一个不同的问题。该应用程序在执行成功时读取所有输出,但在执行失败时无法返回。我只在控制台中收到一条消息。
【解决方案2】:
FileNotFoundError' object has no attribute 'output'

使用

print("Error: " + error)

FileNotFoundErrr 具有这些可能有用的属性:

 args
 characters_written
 errno
 filename
 filename2

【讨论】:

  • 太棒了!我无法弄清楚如何在文档中找到这些属性?如何搜索它们?
  • 您可以在 Python 控制台上使用dict(FileNotFoundError)
  • @Zingam: help(FileNotFoundError)
  • @Tichodroma dict(FileNotFoundError) 返回 TypeError: 'type' object is not iterable
猜你喜欢
  • 2021-08-09
  • 1970-01-01
  • 2012-09-05
  • 1970-01-01
  • 1970-01-01
  • 2019-07-30
  • 1970-01-01
  • 2020-12-17
  • 1970-01-01
相关资源
最近更新 更多