在Python中处理管道和子进程时有些亮点?

时间:2010-08-14 06:15:13

标签: python shell process pipe

我正在努力解决子流程和管道背后的概念,并在Python上下文中使用它们。如果有人能够对这些问题有所了解,那将真正帮助我。

  1. 说我的管道设置如下

    createText.py | processText.py | cat

    processText.py正在通过stdin接收数据,但这是如何实现的?它是如何知道没有更多数据将会出现并且应该退出?我的猜测是它可以寻找一个EOF并根据它终止,但是如果createText.py永远不会发送一个呢?这会在createText.py的部分被视为错误吗?

  2. 假设parent.py启动子子进程(child.py)并调用wait()以等待子进程完成。如果父母将孩子的stdout和stderr作为管道捕获,在孩子终止后是否仍然可以安全地从他们那里读取?或者当一端终止时,管道(及其中的数据)被破坏了吗?

  3. 我想解决的一般问题是编写一个python脚本,该脚本使用Popen类多次调用rsync。我希望我的程序等到rsync完成,然后我想检查返回状态以查看它是否正确退出。如果没有,我想阅读孩子的stderr,看看错误是什么。这是我到目前为止所拥有的

    # makes the rsync call.  Will block until the child
    # process is finished.  Returns the exit code for rsync
    def performRsync(src, dest):
        print "Pushing " + src + " to " + dest
        child = Popen(['rsync', '-av', src, dest], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        child.wait()    
        ## check for success or failure
        ## 0 is a successful exit code here
        if not child.returncode:
            return True 
        else:#ballz
            stout, sterr = child.communicate()
            print "ERR pushing " + src + ". " + sterr
            return False
    
  4. 更新:我也遇到过这个问题。考虑这两个简单的文件:

    # createText.py
    for x in range(1000):
        print "creating line " + str(x)
        time.sleep(1)
    
    # processText.py
    while True:
        line = sys.stdin.readline()
        if not line:
            break;
        print "I modified " + line
    

    为什么processText.py在这种情况下不会开始打印,因为它从stdin获取数据?管道在传递之前是否收集了一些缓冲数据?

1 个答案:

答案 0 :(得分:1)

这假设是UNIXish / POSIXish环境。

管道中的EOF不再需要读取数据,即read()返回长度为0.这通常发生在左侧进程退出并关闭其stdout时。由于您无法从另一端关闭的管道中读取,因此processText中的read表示EOF。

如果createText没有退出,从而关闭它的输出,那么它将是一个非结束程序,它在管道中是一件坏事。即使不在管道中,一个永远不会结束的程序通常也是错误的(奇怪的情况,如yes(1)除外)。

只要您没有获得EOF或IOError(errno.EPIPE)指示,您也可以从管道读取,这也表明没有任何内容可供阅读。

我没有测试过您的代码,是否有意外的事情?