子流程错误处理漏掉

subprocess error handling slipping through

我被困在这个问题上有一段时间了。基本上我遵循了一些子流程使用示例,但我想我一定有其他问题。

我正在编写一个脚本,该脚本遍历电影文件的目录并对每个文件运行 exiftool 以提取有关它们的一些信息。

我可以让它工作,直到遇到 exiftool 错误的情况。例如 Error: File format error ... 所以我试图捕获该错误或 exiftool 生成的任何错误(即使错误消息作为变量也很方便),然后跳过该文件。

在下面的代码中,myArg 只是文件的路径。

try:
    proc = subprocess.Popen(["exiftool", "-s", "-ImageWidth", "-ImageHeight", "-VideoFrameRate", "-CompressorName", "-MediaDuration", myArg], stdout=subprocess.PIPE)
    (out, err) = proc.communicate()
except OSError:
    print "Pass, something is borked..."
    pass

如果我理解正确,你想传递读取文件时可能发生的任何错误,如果是这样,那么一般的错误处理,而不是 OsError

except Exception as e:
   print "Error Descr"+ str(e)
   pass

有很多方法可以做到这一点。如果您只想要 return 代码,则可以使用 subprocess.call

import subprocess

ret = subprocess.call(['ls', 'sadknlsknfd'])
if ret:
    print('Something is borked\nreturncode:%i' % ret)

# Something is borked
# returncode:2

subprocess.check_call引发异常:

try:
    subprocess.check_call(['ls', 'sadknlsknfd'])
except subprocess.CalledProcessError as e:
    print('Something is borked\ncommand: %s\noutput: %s\nreturncode:%i'
          % (e.cmd, e.output, e.returncode))

# Something is borked
# command: ['ls', 'sadknlsknfd']
# output: None
# returncode:2

或者如果你也想要输出,你可以使用 subprocess.check_output:

try:
    # note that `out` will be undefined if the call fails
    out = subprocess.check_output(['ls', 'sadknlsknfd'])
except subprocess.CalledProcessError as e:
    print('Something is borked\ncommand: %s\noutput: %s\nreturncode:%i'
          % (e.cmd, e.output, e.returncode))

# Something is borked
# command: ['ls', 'sadknlsknfd']
# output: 
# returncode:2

要同时获取 STDERR 消息,您可以 redirect it to STDOUT:

try:
    out = subprocess.check_output(['ls', 'sadknlsknfd'], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
    # `out` will be undefined if the call fails
    print('Something is borked\ncommand: %s\noutput: %s\nreturncode:%i'
          % (e.cmd, e.output, e.returncode))

# Something is borked
# command: ['ls', 'sadknlsknfd']
# output: ls: cannot access sadknlsknfd: No such file or directory

# returncode:2

您也可以这样使用 subprocess.Popen.communicate

p = subprocess.Popen(['ls', 'saddsfsdf'],
                     stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(out, err) = p.communicate()
ret = p.returncode
if ret:
    print('Something is borked\nstdout:%s\nstderr:%s\nretcode:%i'
          % (out, err, ret))

# Something is borked
# stdout:
# stderr:ls: cannot access saddsfsdf: No such file or directory

# retcode:2

我认为您正在寻找的是从 exiftool 获取退出代码。它应该 return 0 成功,因此要检查错误,您可以在 proc.communicate():

之后添加
if proc.returncode != 0:
    print "Pass, something is borked..."

如果错误消息发送到标准输出,您应该将其放入 out 变量中。如果它转到 stderr,请将 stderr=subprocess.PIPE 添加到您的 pOpen 命令,然后它应该在 err.