【问题标题】:how to catch subprocess call exception in python?如何在python中捕获子进程调用异常?
【发布时间】:2021-09-28 09:20:53
【问题描述】:

我有一个python代码如下:

    try:
        print("Running code " + str(sub.id))
        r = subprocess.call("node codes.js > outputs.txt", shell=True)
    except:
        print("Error running submission code id " + str(sub.id))

代码正在使用 subprocess.call 运行节点命令。 node 命令正在运行 codes.js 文件。有时如果代码中有错误,例如是否有文档。命令然后代码抛出错误。

使用 try 和 except 不会捕获 node 命令失败时抛出的错误。

抛出的错误如下

有文件。代码中的行,因此节点无法理解该行,因此会引发错误。

/home/kofhearts/homework/codes.js:5
                document.getElementById("outputalert").innerHTML = "Hacked";
                ^

ReferenceError: document is not defined
    at solve (/home/kofhearts/homework/codes.js:5:3)
    at Object.<anonymous> (/home/kofhearts/homework/codes.js:13:28)
    at Module._compile (internal/modules/cjs/loader.js:1068:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1097:10)
    at Module.load (internal/modules/cjs/loader.js:933:32)
    at Function.Module._load (internal/modules/cjs/loader.js:774:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
    at internal/main/run_main_module.js:17:47
Traceback (most recent call last):
  File "manage.py", line 22, in <module>
    main()
  File "manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "/home/kofhearts/.virtualenvs/myenv/lib/python3.7/site-packages/django/core/management/__init__.py", line 401, in execute_from_command_line
    utility.execute()
  File "/home/kofhearts/.virtualenvs/myenv/lib/python3.7/site-packages/django/core/management/__init__.py", line 395, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/kofhearts/.virtualenvs/myenv/lib/python3.7/site-packages/django/core/management/base.py", line 330, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/kofhearts/.virtualenvs/myenv/lib/python3.7/site-packages/django/core/management/base.py", line 371, in execute
    output = self.handle(*args, **options)
  File "/home/kofhearts/homework/assignments/management/commands/police.py", line 73, in handle
    if isCorrect(data.strip()[:-1], sub.question.outputs, sub.question, sub.code):
  File "/home/kofhearts/homework/assignments/views.py", line 566, in isCorrect
    givenans = [json.loads(e.strip()) for e in received.split('|')]
  File "/home/kofhearts/homework/assignments/views.py",

当 subprocess.call 失败时如何捕获错误?感谢您的帮助!

【问题讨论】:

  • 是的,subprocess.call() 的文档中提到了它。引用:“需要捕获标准输出或标准错误的代码应使用run() 代替”subprocess.run("node codes.js &gt; outputs.txt", capture_output=True)。请注意确定它是否适用于重定向输出,可能最好使用 python 脚本编写文件..

标签: python python-3.x subprocess


【解决方案1】:

如何在 subprocess.call 失败时捕获错误?

执行此操作的“标准”方法是使用subprocess.run

from subprocess import run, CalledProcessError
cmd = ["node", "code.js"]
try:
    r = run(cmd, check=True, capture_output=True, encoding="utf8")
    with open("outputs.txt", "w") as f:
        f.write(r.stdout)
except CalledProcessError as e:
    print("oh no!")
    print(e.stderr)

请注意,我已经放弃了重定向并在 python 中完成了它。您可能可以使用shell=True 进行重定向,但这是一个完整的安全漏洞,您不需要将标准输出发送到文件。

check=True 确保它将以非零返回状态抛出。

capture_output=True 很方便,因为stderrstdout 被传递到异常,允许您在那里检索它们。感谢@OlvinR​​oght 指出这一点。

最后,可以手动检查:

r = run(cmd, capture_output=True, encoding="utf8")
if r.returncode:
    print("Failed", r.stderr, r.stdout)
else:
    print("Success", r.stdout)

我通常会避免这种模式

  • 尝试成功是免费的(我们希望这会成功)
  • 捕获异常是我们通常处理问题的方式,所以这是正确的方法 (TM)

但是YMMV。

【讨论】:

  • 您也可以在没有try .. except 子句的情况下实现相同的功能。如果r.returncode 不为零 - 这是一个错误,您可以打印e.stderr 否则只需打印e.stdout。它应该有更好的性能。 (P.S.不要删除你当前的代码,这很好,如果你想添加一个选项就可以了).
  • @OlvinR​​oght 确实如此。在频繁错误的情况下它会更高效(尽管在没有错误的情况下性能会降低,因为try 可以免费获得成功),但我觉得这是一个微优化,无论如何 OP 希望它扔。
猜你喜欢
  • 1970-01-01
  • 2017-12-29
  • 2011-05-17
  • 1970-01-01
  • 1970-01-01
  • 2018-03-28
  • 2020-02-17
  • 2021-01-29
  • 2010-09-12
相关资源
最近更新 更多