subprocess.run()的输出为空

3
以下是命令:

    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()

当正确的密码被提供且两个打印语句按预期工作时,它的工作效果很好。

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):

你的问题是什么?在我看来,标题有些混淆,因为你给出了一个输出的例子,另一个例子却得到了异常。然而,标题说“输出为空”... - wovano
3个回答

2

您还可以捕获subprocess.CalledProcessError异常。该异常的属性保存了参数、退出代码以及标准输出和标准错误输出(如果已被捕获)。

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

很酷,非常感谢。如果我没错的话,它将在此处失败并退出脚本? 我的意思是,脚本不会进一步处理,对吗? - Chel MS

0

两点注意:

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

请参见 文档

如果 check 为 true,并且进程以非零退出代码退出,则会引发 CalledProcessError 异常。该异常的属性保持参数、退出代码以及如果捕获它们的话,标准输出和标准错误输出。

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

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

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

这将在系统的标准输出(即控制台)上打印进程的标准输出。如果您想捕获标准输出,应改用 stdout=subprocess.PIPE(或使用 capture_output=True,这是设置 stdoutstderr 参数的另一种方式)。

-1

尝试这个(添加 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()

1
我的错,我没有将其作为问题的一部分添加。是的,我也尝试过了,但会抛出以下错误:File "/usr/local/lib/python3.5/subprocess.py", line 693, in run with Popen(*popenargs, **kwargs) as process: TypeError: __init__() got an unexpected keyword argument 'capture_output' - Chel MS
2
capture_output 要求使用 Python 版本 3.7 或更高版本,详见文档 - Karl Knechtel
文档明确指出:“capture_output 参数与 stdoutstderr 参数不能同时提供。” - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接