Python 使用StringIO作为标准输入与Popen
我想用Python编写以下shell脚本(当然Python 使用StringIO作为标准输入与Popen,python,subprocess,Python,Subprocess,我想用Python编写以下shell脚本(当然grep.实际上是一个更复杂的命令): 我尝试了这个(它缺少一个与cat日志文件相当的文件): 但是我得到了错误AttributeError:StringIO实例没有属性“fileno” 我知道我应该使用subprocess.communicate()而不是StringIO来向grep进程发送字符串,但我不知道如何将字符串和文件混合使用。除了之外,不要使用裸,它可能会捕获太多。在Python 3中: p = subprocess.Popen(['gr
grep.
实际上是一个更复杂的命令):
我尝试了这个(它缺少一个与cat日志文件
相当的文件):
但是我得到了错误AttributeError:StringIO实例没有属性“fileno”
我知道我应该使用
subprocess.communicate()
而不是StringIO来向grep
进程发送字符串,但我不知道如何将字符串和文件混合使用。除了之外,不要使用裸,它可能会捕获太多。在Python 3中:
p = subprocess.Popen(['grep', '...'], stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
output, output_err = p.communicate(myfile.read())
#!/usr/bin/env python3
from subprocess import check_output
try:
file = open('somefile', 'rb', 0)
except FileNotFoundError:
output = check_output(cmd, input=b'somefile not found')
else:
with file:
output = check_output(cmd, stdin=file)
它适用于大型文件(文件在文件描述符级别重定向,无需将其加载到内存中)
如果您有一个类似文件的对象(没有真正的.fileno()
);您可以使用.write()
方法直接写入管道:
#!/usr/bin/env python3
import io
from shutil import copyfileobj
from subprocess import Popen, PIPE
from threading import Thread
try:
file = open('somefile', 'rb', 0)
except FileNotFoundError:
file = io.BytesIO(b'somefile not found')
def write_input(source, sink):
with source, sink:
copyfileobj(source, sink)
cmd = ['grep', 'o']
with Popen(cmd, stdin=PIPE, stdout=PIPE) as process:
Thread(target=write_input, args=(file, process.stdin), daemon=True).start()
output = process.stdout.read()
不能使用StringIO
对象提供流程输入;改为使用subprocess.PIPE
。@MartijnPieters如我所说(最后一句),“我知道我应该使用subprocess.communicate()而不是StringIO将字符串发送到grep进程,但我不知道如何混合字符串和文件。”为什么不从打开的文件对象读取,写入管道?如果没有打开的文件,写下替代文本。为什么不使用grep呢?哦,好的。您可以使用一些库以完全python的方式来完成它。但是我明白你的意思。这不是把myfile
的全部内容读入内存,为它分配一个字符串,等等吗。?是否应该有一种方法将文件句柄直接传递给下一个进程?使用copyfileobj()
的简洁建议。你能编辑你的答案来澄清为什么需要一个线程吗?我想在读取进程
es输出时需要避免死锁。@smbear如果不使用线程(或async.io),您认为会发生什么?
#!/usr/bin/env python3
from subprocess import check_output
try:
file = open('somefile', 'rb', 0)
except FileNotFoundError:
output = check_output(cmd, input=b'somefile not found')
else:
with file:
output = check_output(cmd, stdin=file)
#!/usr/bin/env python3
import io
from shutil import copyfileobj
from subprocess import Popen, PIPE
from threading import Thread
try:
file = open('somefile', 'rb', 0)
except FileNotFoundError:
file = io.BytesIO(b'somefile not found')
def write_input(source, sink):
with source, sink:
copyfileobj(source, sink)
cmd = ['grep', 'o']
with Popen(cmd, stdin=PIPE, stdout=PIPE) as process:
Thread(target=write_input, args=(file, process.stdin), daemon=True).start()
output = process.stdout.read()