如何在 python 中捕获子进程调用异常?

how to catch subprocess call exception in python?

我有一个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 的节点命令。节点命令是运行codes.js文件。有时如果代码有错误,比如有文档。命令然后代码抛出错误。

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

抛出的错误如下

有文档。代码中的一行,因此节点无法理解该行,因此会抛出错误。

/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 失败时如何捕获错误?感谢您的帮助!

How is it possible to catch the error when subprocess.call fails?

'standard' 方法是使用 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 确保它会抛出非零 return 状态。

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。