subprocess.run() 的输出为空

subprocess.run()'s output is empty

下面是命令:

    try:
        op = subprocess.run(['docker', 'login', '-u', 'username', '-p', 'password', 'dockerhub.com'], check=True, stdout=sys.stdout, stderr=subprocess.PIPE)
        print("Docker stdout :", op.stdout)
        print("Docker Error :", op.stderr.decode("utf-8"))
    except:
    traceback.print_exc()

当提供正确的密码并且 2 个打印语句按预期工作时,它运行良好。

Login Succeeded
Docker stdout : None
Docker Error :

如果密码不正确,我想捕获 运行 在 shell(bash) 上看到的输出,如下所示:

Error response from daemon: Get https://dockerhub.com/v2/: unknown: Bad credentials

相反,我收到了回溯,其中没有看到上述错误消息。

Traceback (most recent call last):
  File "/home/scripts/test.py", line 54, in my_func
    op = subprocess.run(['docker', 'login', '-u', 'username', '-p', 'incorrectpassword', 'dockerhub.com'], check=True, stdout=sys.stdout, stderr=subprocess.PIPE)
  File "/usr/local/lib/python3.5/subprocess.py", line 708, in run
    output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['docker', 'login', '-u', 'username', '-p', 'incorrectpassword', 'dockerhub.com']' returned non-zero exit status 1
Traceback (most recent call last):

试试这个(添加 capture_output=True )

try:
    op = subprocess.run(['docker', 'login', '-u', 'username', '-p', 'password', 'dockerhub.com'], check=True, stdout=sys.stdout, stderr=subprocess.PIPE,capture_output=True)
    print("Docker stdout :", op.stdout)
    print("Docker Error :", op.stderr.decode("utf-8"))
except:
traceback.print_exc()

你也可以抓到 subprocess.CalledProcessError Exception. Attributes of that exception hold the arguments, the exit code, and stdout and stderr 如果他们被捕获了。

try:
    op = subprocess.run(['docker', 'login', '-u', 'username', '-p', 'password', 'dockerhub.com'], check=True, stdout=sys.stdout, stderr=subprocess.PIPE)
    print("Docker stdout :", op.stdout)
except subprocess.CalledProcessError as e:
    exit_code = e.returncode
    stderror = e.stderr
    print(exit_code, stderror)

两个备注:

1: 您用 check=True 呼叫了 subprocess.run()。这会导致您观察到的异常。

参见 documentation:

If check is true, and the process exits with a non-zero exit code, a CalledProcessError exception will be raised. Attributes of that exception hold the arguments, the exit code, and stdout and stderr if they were captured.

最简单的解决方案是使用 check=False(这是默认值,因此您可以直接删除该参数)。然后,在 subprocess.run() 完成后,检查 op.returncodeop.stderr

或者,您可以使用 check=True 并捕获异常,其他答案中也提到了这一点。

2:您使用了stdout=sys.stdout, stderr=subprocess.PIPE.

这会将进程的标准输出打印到系统的标准输出(即控制台)。如果你想捕获标准输出,你应该使用 stdout=subprocess.PIPE 代替(或使用 capture_output=True,这是设置 stdoutstderr 参数的另一种方法)。