2012-12-17 39 views
2

我正在编译一个命令在python unix系统上执行,包含多个管道步骤。例如: -错误检查管道命令在python中为unix

grep foo myfile | cmd1 | cmd2 > output 

这些对应于在具有foo在他们myfile条目的一系列的变换。我有时将其构造为os.system执行的命令,在其他情况下使用subprocess模块执行。

如何从Python中对管道的每个部分执行错误检查?例如,在99%的情况下,myfile中有foo条目,其余管道工程。但是,如果由于某种原因myfile存在但不包含foo条目,则管道的其余部分会因为管道空文件而中断,而其余命令需要非空输入才能工作。这使得它很难调试,因为你看到的是一个破裂的管道输出,不知道这中间步骤失败。

有没有一种方法来构建Python中的错误检查中间步骤的管道?例如。检查管道的grep部分是否确实包含某些输出,grep的输入上的cmd1输出是否还包含某些输出,依此类推?谢谢。

+0

做到这一点,最简单的方法是做事情本地在Python中。调用从OS来回和Python只是引入了额外的变量和通常最好在第一时间避免了复杂性。 –

+0

所以,你会怎么做它在Python,如果它需要调用外部命令?我知道的唯一方法是''subprocess''。我无法改写我在Python中调用的所有命令 – user248237dfsf

+2

在bash中,您有PIPESTATUS变量 - 如果可以的话使用。 否则就像在sr2222建议的python中那样做 - 设置管道,用重定向输入输出启动程序,检查它们的退出状态,那有什么问题?你提到的模块甚至以stdin/stdout/stderr作为参数! – loreb

回答

0

这是我的方法,在Python 2.6 Linux上测试过。

a.Define的方法

def run_command(command): 
    p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
    out, err = p.communicate() 
    return (p.returncode, out, err) 

b。使用它通过以下方式

def test_run_command_pipestatus(self): 
    # the exit $PIPESTATUS is the return code of "exit 2". The default return code is the return code of last command in the pipe 
    return_code, out, err = run_command("exit 2 | tail -n 1; exit $PIPESTATUS") 
    print "return_code = %d" %return_code 
    print out 
    print err 
    self.assertEqual(2, return_code) 
0

基本上一样岷江石的回答,其中有大部分是你所需要的关键信息,但没有额外的功能,并修复问题。 (并在python 2.7.12和3.5.2中测试)

$ PIPESTATUS在sh中不存在,所以如果您的发行版没有/bin/sh,就像bash(比如Ubuntu其使用dash)。它是一个数组,所以我更喜欢像一个一样使用它。

,我建议wait()代替communicate(),这样你就可以(为你处理任何前要在内存读入一个小缓冲区,而不是全负荷输出的使用),而不是过滤啜食的。

因此,所有你需要做的是:

  • 应该使用一个字符串,而不是为ARGS
  • 使用外壳列表=真
  • 使用可执行= “/斌/庆典”

代码:

p = subprocess.Popen("false | true; exit ${PIPESTATUS[0]}", shell=True, executable='/bin/bash', stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

# at this point you do your filtering, eg. using p.stdout.readinto(buf) 

p.wait() 
if p.returncode != 0: 
    # handle it here