python3中CalledProcessError之后的子进程输出

时间:2016-09-27 10:46:59

标签: python python-3.x subprocess

我尝试使用bandit从Python中运行subprocess。我有这样的代码:

import subprocess

command = ['bandit', '-r', 'goodcode']
output = subprocess.check_output(command)
print(output.decode())

这很好用,并给我一个这样的字符串输出:

Run started:2016-09-27 10:37:17.567678

Test results:
        No issues identified.

Code scanned:
        Total lines of code: 940
        Total lines skipped (#nosec): 0

Run metrics:
        Total issues (by severity):
                Undefined: 0
                Low: 0
                Medium: 0
                High: 0
        Total issues (by confidence):
                Undefined: 0
                Low: 0
                Medium: 0
                High: 0
Files skipped (0):

...但是,当我在bandit返回一些错误的目录上运行它时,bandit进程本身返回1.因此我必须像CalledProcessError那样捕获:

import subprocess

command = ['bandit', '-r', 'badcode']

try:
    output = subprocess.check_output(command)
except subprocess.CalledProcessError as e:
    output = e.output

print(output.decode())

...这给了我以下结果:

b"Run started:2016-09-27 10:42:26.616123\n\nTest results:\n>> Issue: [B110:try_except_pass] Try, Except, Pass detected.\n   Severity: Low   Confidence: High\n   Location: badcode/conf/settings_development.py:93\n92\t    from .settings_local import *\n93\texcept:\n94\t    pass\n\n--------------------------------------------------\n>> Issue: [B105:hardcoded_password_string] Possible hardcoded password: 'password'\n   Severity: Low   Confidence: Medium\n   Location: badcode/frontend/tests/test_views.py:21\n20\t        form['username'] = self.user.username\n21\t        form['password'] = 'password'\n22\t\n\n--------------------------------------------------\n>> Issue: [B105:hardcoded_password_string] Possible hardcoded password: 'password'\n   Severity: Low   Confidence: Medium\n   Location: badcode/frontend/tests/test_views.py:35\n34\t        form['username'] = self.user.username\n35\t        form['password'] = 'password'\n36\t\n\n--------------------------------------------------\n>> Issue: [B110:try_except_pass] Try, Except, Pass detected.\n   Severity: Low   Confidence: High\n   Location: badcode/reasons/views.py:234\n233\t                nr = subject.number\n234\t            except:\n235\t                pass\n\n--------------------------------------------------\n>> Issue: [B110:try_except_pass] Try, Except, Pass detected.\n   Severity: Low   Confidence: High\n   Location: badcode/reasons/views.py:277\n276\t                nr = event.number\n277\t            except:\n278\t                pass\n\n--------------------------------------------------\n>> Issue: [B110:try_except_pass] Try, Except, Pass detected.\n   Severity: Low   Confidence: High\n   Location: badcode/retention/migrations/0010_auto_20160527_1603.py:13\n12\t            retention.save()\n13\t        except:\n14\t            pass\n\n--------------------------------------------------\n>> Issue: [B110:try_except_pass] Try, Except, Pass detected.\n   Severity: Low   Confidence: High\n   Location: badcode/retention/migrations/0015_auto_20160623_1051.py:13\n12\t            retention.save()\n13\t        except:\n14\t            pass\n\n--------------------------------------------------\n>> Issue: [B108:hardcoded_tmp_directory] Probable insecure usage of temp file/directory.\n   Severity: Medium   Confidence: Medium\n   Location: badcode/utils/views.py:322\n321\t        css = '{}/static/badcode/css/screen.css'.format(settings.ROOT_DIR)\n322\t        location = '/tmp/{}.pdf'.format(filename)\n323\t\n\n--------------------------------------------------\n\nCode scanned:\n\tTotal lines of code: 15287\n\tTotal lines skipped (#nosec): 0\n\nRun metrics:\n\tTotal issues (by severity):\n\t\tUndefined: 0.0\n\t\tLow: 7.0\n\t\tMedium: 1.0\n\t\tHigh: 0.0\n\tTotal issues (by confidence):\n\t\tUndefined: 0.0\n\t\tLow: 0.0\n\t\tMedium: 3.0\n\t\tHigh: 5.0\nFiles skipped (0):\n"

请注意,b""位于字符串中,因此output[0] == 'b'output[1] == '"'。为什么是这样?如果进程返回0,那么e.output是否应该将输出编码为与output相同?

1 个答案:

答案 0 :(得分:2)

在第二种情况下调用output方法之前,您似乎已查看.decode()变量。 output在两种情况下都指的是相同的字节串。

>>> import subprocess, sys
>>> output1 = subprocess.check_output([sys.executable, '-c', 'print("abc")'])
>>> try:
...   subprocess.check_output([sys.executable, '-c', 
...                            'print("abc"); import sys;sys.exit(1)'])
... except subprocess.CalledProcessError as e:
...   output2 = e.output
... 
>>> output1 == output2
True

如果非零退出状态不是您的错误,那么您可以使用在这种情况下不会引发CalledProcessError的函数:

#!/usr/bin/env python3
from subprocess import run, PIPE

finished_process = run(command, stdout=PIPE, universal_newlines=True)
print("{p.returncode}, {p.stdout}".format(p=finished_process))
# e.g.: 1, abc

universal_newlines=True是"启用文字模式"的一个模糊拼写。这里。