如果我这样做:
import subprocess
from cStringIO import StringIO
subprocess.Popen(['grep','f'],stdout=subprocess.PIPE,stdin=StringIO('one\ntwo\nthree\nfour\nfive\nsix\n')).communicate()[0]
我得到:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "/build/toolchain/mac32/python-2.4.3/lib/python2.4/subprocess.py", line 533, in __init__
(p2cread, p2cwrite,
File "/build/toolchain/mac32/python-2.4.3/lib/python2.4/subprocess.py", line 830, in _get_handles
p2cread = stdin.fileno()
AttributeError: 'cStringIO.StringI' object has no attribute 'fileno'
显然是cStringIO。StringIO对象的嘎嘎声不够接近文件鸭子,不适合subprocess.Popen。我怎么解决这个问题呢?
Beware that Popen.communicate(input=s)may give you trouble ifsis too big, because apparently the parent process will buffer it before forking the child subprocess, meaning it needs "twice as much" used memory at that point (at least according to the "under the hood" explanation and linked documentation found here). In my particular case,swas a generator that was first fully expanded and only then written tostdin so the parent process was huge right before the child was spawned,
and no memory was left to fork it:
文件“/opt/local/stow/python-2.7.2/lib/python2.7/subprocess.py”,第1130行,在_execute_child中
自我。Pid = os.fork()
OSError: [Errno 12]不能分配内存
在Python 3.7+上这样做:
my_data = "whatever you want\nshould match this f"
subprocess.run(["grep", "f"], text=True, input=my_data)
并且您可能希望添加capture_output=True以获得以字符串形式运行命令的输出。
在旧版本的Python中,将text=True替换为universal_newlines=True:
subprocess.run(["grep", "f"], universal_newlines=True, input=my_data)
这对于grep来说有点过分了,但是通过我的学习,我已经了解了Linux命令expect和python库pexpect
期望:对话与互动程序
pexpect:用于生成子应用程序的Python模块;控制他们;并在他们的输出中响应预期的模式。
import pexpect
child = pexpect.spawn('grep f', timeout=10)
child.sendline('text to match')
print(child.before)
使用pexpect使用交互式shell应用程序(如ftp)非常简单
import pexpect
child = pexpect.spawn ('ftp ftp.openbsd.org')
child.expect ('Name .*: ')
child.sendline ('anonymous')
child.expect ('Password:')
child.sendline ('noah@example.com')
child.expect ('ftp> ')
child.sendline ('ls /pub/OpenBSD/')
child.expect ('ftp> ')
print child.before # Print the result of the ls command.
child.interact() # Give control of the child to the user.