Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python,子进程:从子进程读取输出_Python_Subprocess_Stdout - Fatal编程技术网

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

python,子进程:从子进程读取输出,python,subprocess,stdout,Python,Subprocess,Stdout,我有以下脚本: #!/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)

我有以下脚本:

#!/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

如果我使用
通信
,我会得到以下结果:

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)
在这里:

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()

但是它又挂起了。

您可能被Python的输出缓冲绊倒了。下面是
python--help
对它的说明

-u     : unbuffered binary stdout and stderr; also PYTHONUNBUFFERED=x
         see man page for details on internal buffering relating to '-u'
使用
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)
本建议来自以下章节:

警告:使用communicate()而不是.stdin.write、.stdout.read或.stderr.read 避免由于任何其他操作系统管道缓冲区填满并阻塞 子进程


我认为这里存在两个问题:

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

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

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

p.stdin.flush()
在子流程脚本中,在打印x[:-1]
之后,在循环中添加以下内容:

sys.stdout.flush()

(和顶部的导入系统)

当您完成对p.stdin的写入时,将其关闭:
p.stdin.close()
子流程方法可用于:

output=子流程。检查输出('./script.py')

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

output=subprocess.check_输出('./script.py',stderr=subprocess.STDOUT)


由于您避免直接管理管道,因此可能会避免您的问题。

如果要将多行代码传递给
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
输出: 或


我能不能在代码中强制Python不要刷新输出?当它被推入管道时,为什么会被缓冲,而当它被简单地打印到屏幕上时,为什么不会呢?是否可以通过编程方式刷新缓冲区?出于性能原因,发送到管道的输出会被缓冲。(逐行刷新效率非常低,但您没有注意到程序何时花费大部分时间等待用户)当刷新到管道时,缓冲显著提高了性能,要么缩短了完成时间,要么减少了CPU负载,这取决于操作的I/O绑定方式。至于以编程方式刷新缓冲,您可以在子进程中尝试
sys.stdout.flush()
,但我从未使用过它,而且以这种方式使用它并不是很好的体系结构。(它更适合作为“同步到磁盘”进程的一部分与
os.fsync
配合使用)最好让父进程根据需要通过
-u
PYTHONUNBUFFERED
环境变量禁用缓冲。这对我不起作用。我对我的问题进行了编辑。他想与子流程进行多次沟通<代码>通信不能这样做。@gruszczy:谢谢你的更新。我更新了答案以解决另一个问题。将
sys.stdout.flush()
添加到脚本中并使用
p.stdout.readline
最终起到了帮助作用。非常感谢你的帮助。谢谢丹尼尔·斯塔茨巴什,让我的生活更轻松。(即使在写入“\n”后仍刷新)“print>>p.stdin,s”语法的作用是什么?我不熟悉“>>”@civil:类似于从导入打印功能中的
之后提供的。
#!/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
#!/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]