简体   繁体   English

使用plumbum捕获前台命令的错误输出

[英]Capture the error output of a foreground command using plumbum

I'm using the plumbum python library (http://plumbum.readthedocs.org/) as a replacement for shell scripts. 我使用plumbum python库(http://plumbum.readthedocs.org/)作为shell脚本的替代品。

There's a command I want to run that, when it fails it outputs the paths to a file I'm interested in: 有一个我想要运行的命令,当它失败时它会输出我感兴趣的文件的路径:

$ slow_cmd
Working.... 0%
Working.... 5%
Working... 15%
FAIL. Check log/output.log for details

I want to run the program on the foreground to check the progress: 我想在前台运行程序来检查进度:

from plumbum.cmd import slow_cmd

try:
    f = slow_cmd & FG
except Exception, e:
    print "Something went wrong."

# Need the error output from f to get the log file :(    

When the slow_cmd fails, it throws the exception (which I can catch). slow_cmd失败时,它会抛出异常(我可以捕获)。 But I cannot obtain the error output from the exception or from the f future object. 但我无法从异常或f future对象获取错误输出。

If I don't run the slow_cmd on the FG, the exception contains all of the output and I can read the file from there. 如果我没有在FG上运行slow_cmd ,则异常包含所有输出,我可以从那里读取文件。

the problem is, FG redirects the output straight to your program's stdout. 问题是, FG将输出直接重定向到程序的标准输出。 see https://github.com/tomerfiliba/plumbum/blob/master/plumbum/commands.py#L611 请参阅https://github.com/tomerfiliba/plumbum/blob/master/plumbum/commands.py#L611

when output is redirected this way, it doesn't go through plumbum's machinery so you won't get it in the exception object. 当输出以这种方式重定向时,它不会通过plumbum的机器,所以你不会在异常对象中得到它。 if you're willing to block until slow_cmd finishes, a better solution would be to read from stdout yourself. 如果你愿意阻止,直到slow_cmd完成,一个更好的解决方案是自己读取stdout。 here's a sketch: 这是草图:

lines = []
p = slow_cmd.popen()
while p.poll() is None:
    line = p.stdout.readline()
    lines.append(line)
    print line
if p.returncode != 0:
    print "see log file..."

a more elegant solution would be to write your own ExecutionModifier (like FG ) that duplicates the output streams. 更优雅的解决方案是编写自己的ExecutionModifier(如FG ),复制输出流。 let's call it TEE (after http://en.wikipedia.org/wiki/Tee_(command) )... i haven't tested it, but it should do the trick (minus select ing on stdout/err): 让我们称之为TEE (在http://en.wikipedia.org/wiki/Tee_(command)之后 )...我还没有测试过它,但它应该做的伎俩(减去select stdout / err):

class TEE(ExecutionModifier):
    def __init__(self, retcode = 0, dupstream = sys.stdout):
        ExecutionModifier.__init__(self, retcode)
        self.dupstream = dupstream
    def __rand__(self, cmd):
        p = cmd.popen()
        stdout = []
        stderr = []
        while p.poll():
            # note: you should probably select() on the two pipes, or make the pipes nonblocking,
            # otherwise readline would block
            so = p.stdout.readline()
            se = p.stderr.readline()
            if so:
                stdout.append(so)
                dupstream.write(so)
            if se:
                stderr.append(se)
                dupstream.write(se)
        stdout = "".join(stdout)
        stderr = "".join(stderr)
        if p.returncode != self.retcode:
            raise ProcessExecutionError(p.argv, p.returncode, stdout, stderr)
        return stdout, stderr

try:
    stdout, stderr = slow_cmd & TEE()
except ProcessExecutionError as e:
    pass # find the log file, etc.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM