如何使用Python捕获subprocess.call错误?

时间:2017-09-07 13:53:02

标签: python docker subprocess

我试图下载特定的Docker镜像,用户将在其中输入版本。但是,如果版本不存在,Docker将抛出错误。

我使用subprocess.call从Python 3管道到终端。

示例代码:

from subprocess import call
containerName = input("Enter Docker container name: ")
swVersion = input("Enter software version: ")

call(["docker", "run", "--name", "{}".format(containerName), 
      "--detach", "--publish", "8080:8080", "user/software:{}".format(swVersion)])

如果找不到版本,则docker将在终端输出:

docker: Error response from daemon: manifest for user/software:8712378 not found.

如何在Python脚本中捕获此错误?

有些事情:

try:
    call(["docker", "run", "--name", "{}".format(containerName), "--detach", "--publish", "8080:8080", "user/software:{}".format(swVersion)])
except:
    # How do I catch the piped response code here?`

3 个答案:

答案 0 :(得分:2)

如果您将程序的输出写入stderr并且不直接与其进行交互,那么最简单的方法就是使用check_call代替call }。 check_call如果其运行的命令以0以外的任何其他状态退出,则会引发异常。

try:
    check_call(["docker", "run", "--name", "{}".format(containerName), "--detach", "--publish", "8080:8080", "user/software:{}".format(swVersion)])
except CalledProcessError:
    print("That command didn't work, try again")

答案 1 :(得分:2)

您可以使用Popen subprocess函数抓取stderr并在python控制台中打印,Documentationsubprocess.call说明

  

注意不要将stdout = PIPE或stderr = PIPE与此函数一起使用   可以基于子进程输出量死锁。使用Popen   需要管道时的communic()方法。

proc = subprocess.Popen(["docker", "run", "--name", "{}".format(containerName), "--detach", "--publish", "8080:8080", "user/software:{}".format(swVersion)],stdout=subprocess.PIPE, stderr=subprocess.PIPE, creationflags=subprocess_flags)
proc.wait()
(stdout, stderr) = proc.communicate()

if proc.returncode != 0:
    print(stderr)
else:
    print("success")

答案 2 :(得分:1)

上面的检查返回代码的答案是可行的,但是更Python化的方式是捕获类似以下的异常:

try:
    proc = subprocess.Popen(["docker", "run", "--name", "{}".format(containerName), "--detach", "--publish", "8080:8080", "user/software:{}".format(swVersion)],stdout=subprocess.PIPE, stderr=subprocess.PIPE, creationflags=subprocess_flags)
    proc.wait()
    (stdout, stderr) = proc.communicate()

except calledProcessError as err:
    print("Error ocurred: " + err.stderr)

所谓的ProcessError是Popen类捕获的错误。

如果您想捕获操作系统或系统级别的常见错误(例如,文件/目录不存在),请添加以下例外:

except OSError as e:
    print ("OSError > ",e.errno)
    print ("OSError > ",e.strerror)
    print ("OSError > ",e.filename)

except:
    print ("Error > ",sys.exc_info()[0])

如果要返回一个返回代码,则应明确地执行此操作,而不是对它进行print()处理。在最后一个except语句之后并与try语句缩进:

return True

如果要返回消息,可以使用Response对象:

return Response ("Success Message")