python 如何保存子进程命令的错误信息到文件

g6ll5ycj  于 12个月前  发布在  Python
关注(0)|答案(3)|浏览(126)

在使用子进程运行bash命令时,我可能会遇到命令无效的情况。在这种情况下,bash会返回错误消息。我们如何捕获此消息?我想将此消息保存到日志文件中。下面是一个示例,我尝试列出不存在的目录中的文件。

try:
    subprocess.check_call(["ls", "/home/non"]) 
    df = subprocess.Popen(["ls", "/home/non"], stdout=subprocess.PIPE)        
    output, err = df.communicate()
    # process outputs
except Exception as error:        
    print error
    sys.exit(1)

字符串
Bash将打印“ls:无法访问/home/non:没有这样的文件或目录”。我怎么能得到这个错误消息?except行捕获的错误显然是不同的,它说“命令'返回' ls ','/home/non ']'返回非零退出状态2”。

oxf4rvwz

oxf4rvwz1#

  • “ls:cannot access /home/non:No such file or directory”* 是ls命令生成的,这里不是bash

如果你想使用异常处理来处理不存在的文件,那么使用subprocess.check_output()

#!/usr/bin/env python
from subprocess import check_output, STDOUT, CalledProcessError

try:
    output = check_output(['ls', 'nonexistent'], stderr=STDOUT)
except CalledProcessError as exc:
    print(exc.output)
else:
    assert 0

字符串

输出

ls: cannot access nonexistent: No such file or directory

0pizxfdo

0pizxfdo2#

您可以将stderr重定向到文件对象:

from subprocess import PIPE, CalledProcessError, check_call, Popen

with open("log.txt", "w") as f:
    try:
        check_call(["ls", "/home/non"], stderr=f)
        df = Popen(["ls", "/home/non"], stdout=PIPE)
        output, err = df.communicate()
    except CalledProcessError as e:
        print(e)
        exit(1)

字符串
输出到log.txt:

ls: cannot access /home/non: No such file or directory


如果您希望在except中显示消息:

try:
    check_call(["ls", "/home/non"])
    df = Popen(["ls", "/home/non"], stdout=PIPE)
    output, err = df.communicate()
except CalledProcessError as e:
    print(e.message)


对于python 2.6,e.message将无法工作。您可以使用python 2.7的check_output的类似版本,它将与python 2.6一起工作:

from subprocess import PIPE, CalledProcessError, Popen

def check_output(*args, **kwargs):
    process = Popen(stdout=PIPE, *args, **kwargs)
    out, err = process.communicate()
    ret = process.poll()
    if ret:
        cmd = kwargs.get("args")
        if cmd is None:
            cmd = args[0]
        error = CalledProcessError(ret, cmd)
        error.out = out
        error.message = err
        raise error
    return out

try:
    out = check_output(["ls", "/home"], stderr=PIPE)
    df = Popen(["ls", "/home/non"], stdout=PIPE)
    output, err = df.communicate()
except CalledProcessError as e:
    print(e.message)
else:
    print(out)

xqnpmsa8

xqnpmsa83#

根据subprocess文档,现在首选run命令。
范例:

import logging
import subprocess

logger = logging.getLogger(__name__)

try:
    subprocess.run(["ls", "-l"], shell=True, check=True, capture_output=True)
except subprocess.CalledProcessError as err:
    logger.error(f"{err} {err.stderr.decode('utf8')}")

字符串
正如其他人所提到的,如果你想保存到一个文件,你可以使用stdout参数到run;但是,你也可以使用use logging to do that,然后在你的方法中记录错误。

相关问题