代码之家  ›  专栏  ›  技术社区  ›  gruszczy

python,子进程:从子进程读取输出

  •  13
  • gruszczy  · 技术社区  · 14 年前

    #!/usr/bin/python
    
    while True:
        x = raw_input()
        print x[::-1]
    

    我是从 ipython :

    In [5]: p = Popen('./script.py', stdin=PIPE)
    
    In [6]: p.stdin.write('abc\n')
    cba
    

    而且效果很好。

    但是,当我这样做时:

    In [7]: p = Popen('./script.py', stdin=PIPE, stdout=PIPE)
    
    In [8]: p.stdin.write('abc\n')
    
    In [9]: p.stdout.read()
    

    翻译挂断了。我做错什么了?我希望能够多次从另一个进程写入和读取,以便将一些任务传递给此进程。我需要做什么不同的事情?

    编辑1

    如果我使用 communicate

    In [7]: p = Popen('./script.py', stdin=PIPE, stdout=PIPE)
    
    In [8]: p.communicate('abc\n')
    Traceback (most recent call last):
      File "./script.py", line 4, in <module>
        x = raw_input()
    EOFError: EOF when reading a line
    Out[8]: ('cba\n', None)
    

    编辑2

    我试过冲:

    #!/usr/bin/python
    
    import sys
    
    while True:
            x = raw_input()
            print x[::-1]
            sys.stdout.flush()
    

    In [5]: from subprocess import PIPE, Popen
    
    In [6]: p = Popen('./script.py', stdin=PIPE, stdout=PIPE)
    
    In [7]: p.stdin.write('abc')
    
    In [8]: p.stdin.flush()
    
    In [9]: p.stdout.read()
    

    但它又挂了。

    6 回复  |  直到 14 年前
        1
  •  15
  •   Daniel Stutzbach Edward Leno    14 年前

    p.stdout.read() ,它将读取所有数据,直到文件结束。然而,您的子脚本在无限循环中运行,所以永远不会发生文件结束。也许你想要 p.stdout.readline() ?

    2) 在交互模式下,大多数程序一次只缓冲一行。当从另一个程序运行时,它们会缓冲更多。在许多情况下,缓冲提高了效率,但在两个程序需要交互通信时会出现问题。

    之后 p.stdin.write('abc\n')

    p.stdin.flush()
    

    在子流程脚本中,在 print x[::-1] 在循环中添加以下内容:

    sys.stdout.flush()
    

    (和 import sys (顶部)

        2
  •  3
  •   JoshD    14 年前

    子流程方法 check_output 可用于:

    output = subprocess.check_output('./script.py')

    输出将是进程的标准输出。如果您也需要标准:

    output = subprocess.check_output('./script.py', stderr=subprocess.STDOUT)

    因为您避免直接管理管道,所以它可能会绕过您的问题。

        3
  •  3
  •   jfs    14 年前

    script.py 然后您需要同时读/写:

    #!/usr/bin/env python
    import sys
    from subprocess import PIPE, Popen
    from threading  import Thread
    
    def print_output(out, ntrim=80):
        for line in out:
            print len(line)
            if len(line) > ntrim: # truncate long output
                line = line[:ntrim-2]+'..'
            print line.rstrip() 
    
    
    if __name__=="__main__":
        p = Popen(['python', 'script.py'], stdin=PIPE, stdout=PIPE)
        Thread(target=print_output, args=(p.stdout,)).start()
        for s in ['abc', 'def', 'ab'*10**7, 'ghi']:
            print >>p.stdin, s
        p.stdin.close()
        sys.exit(p.wait()) #NOTE: read http://docs.python.org/library/subprocess.html#subprocess.Popen.wait
    

    输出:

    4
    cba
    4
    fed
    20000001
    bababababababababababababababababababababababababababababababababababababababa..
    4
    ihg

    脚本.py :

    #!/usr/bin/env python
    """Print reverse lines."""
    while True:
        try: x = raw_input()
        except EOFError:
            break # no more input
        else:
            print x[::-1]
    

    或者

    #!/usr/bin/env python
    """Print reverse lines."""
    import sys
    
    for line in sys.stdin:
        print line.rstrip()[::-1]
    

    #!/usr/bin/env python
    """Print reverse lines."""
    import fileinput
    
    for line in fileinput.input(): # accept files specified as command line arguments
        print line.rstrip()[::-1]
    
        4
  •  1
  •   ssokolow    14 年前

    您可能被Python的输出缓冲绊倒了。这是什么 python --help 我不得不说。

    -u     : unbuffered binary stdout and stderr; also PYTHONUNBUFFERED=x
             see man page for details on internal buffering relating to '-u'
    
        5
  •  1
  •   Thud Foo    14 年前

    写入p.stdin后,请关闭它: p.stdin.close()

        6
  •  -3
  •   David Narayan    14 年前

    使用 communicate() .stdout.read() .

    例子:

    from subprocess import Popen, PIPE
    p = Popen('./script.py', stdin=PIPE, stdout=PIPE, stderr=PIPE)
    input = 'abc\n'
    stdout, stderr = p.communicate(input)
    

    这项建议来自 Popen objects 中的节 subprocess documentation

    警告 :使用communicate()而不是。标准写入, .标准读取或者。标准阅读 避免由于任何其他操作系统管道缓冲区填满并阻塞 子进程。