pythonsubprocess中的多个input和输出进行通信
我需要做这样的事情,但我需要创build一个可以给予input和输出多次的subprocess。 该post的接受答案有很好的代码…
from subprocess import Popen, PIPE, STDOUT p = Popen(['grep', 'f'], stdout=PIPE, stdin=PIPE, stderr=STDOUT) grep_stdout = p.communicate(input=b'one\ntwo\nthree\nfour\nfive\nsix\n')[0] print(grep_stdout.decode()) # four # five
…我想继续像这样:
grep_stdout2 = p.communicate(input=b'spam\neggs\nfrench fries\nbacon\nspam\nspam\n')[0] print(grep_stdout2.decode()) # french fries
但是,唉,我得到以下错误:
Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/subprocess.py", line 928, in communicate raise ValueError("Cannot send input after starting communication") ValueError: Cannot send input after starting communication
如果我理解正确,proc.stdin.write()方法不能使您收集输出。 保持持续input/输出的线路最简单的方法是什么?
编辑:====================
看起来像pexpect
是一个有用的图书馆,我正在尝试做,但我有麻烦得到它的工作。 这里是对我的实际任务的更全面的解释。 我正在使用hfst
来获取单个(俄语)单词的语法分析。 以下演示了它在bash shell中的行为:
$ hfst-lookup analyser-gt-desc.hfstol > слово слово слово+N+Neu+Inan+Sg+Acc 0.000000 слово слово+N+Neu+Inan+Sg+Nom 0.000000 > сработай сработай сработать+V+Perf+IV+Imp+Sg2 0.000000 сработай сработать+V+Perf+TV+Imp+Sg2 0.000000 >
我希望我的脚本能够一次获得一种forms的分析。 我试过这样的代码,但它不工作。
import pexpect analyzer = pexpect.spawnu('hfst-lookup analyser-gt-desc.hfstol') for newWord in ['слово','сработай'] : print('Trying', newWord, '...') analyzer.expect('> ') analyzer.sendline( newWord ) print(analyzer.before) # trying слово ... # # trying сработай ... # слово # слово слово+N+Neu+Inan+Sg+Acc 0.000000 # слово слово+N+Neu+Inan+Sg+Nom 0.000000 # #
我明显误解了pexpect.before
做了什么。 我怎样才能得到每个单词的输出?
Popen.communicate()
是一种帮助方法,它将数据一次写入stdin
并创build线程从stdout
和stderr
提取数据。 它完成写入数据时closuresstdin
,并读取stdout
和stderr
直到这些pipe道closures。 你不能做第二次communicate
因为孩子已经退出了。
与subprocess的交互会话比较复杂。
一个问题是,儿童进程是否认识到它应该是互动的。 在大多数命令行程序用于交互的C库中,从terminal(例如,Linux控制台或“pty”伪terminal)运行的程序是交互式的并且经常刷新其输出,但是通过PIPES从其他程序运行的程序是非交互式的,交互和刷新他们的输出不经常。
另一个是你应该如何阅读和处理stdout
和stderr
没有死锁。 例如,如果你阻止阅读stdout
,但stderr
填充它的pipe道,孩子会停下来,你卡住了。 您可以使用线程将两者拉入内部缓冲区。
还有一个就是如何处理一个意外退出的孩子。
对于linux和OSX等“unixy”系统, pexpect
模块是为处理交互式subprocess的复杂性而编写的。 对于Windows而言,我不知道要做什么。
这个答案应该归因于@JFSebastian。 感谢您的意见!
下面的代码得到了我预期的行为:
import pexpect analyzer = pexpect.spawnu('hfst-lookup analyser-gt-desc.hfstol') analyzer.expect('> ') for newWord in ['слово','сработай'] : print('Trying', newWord, '...') analyzer.sendline( newWord ) analyzer.expect('> ') print(analyzer.before)
每当你想发送input到进程,使用proc.stdin.write()
。 每当你想从stream程中获得输出,使用proc.stdout.read()
。 构造函数的stdin
和stdout
参数都需要设置为PIPE
。