我有以下我想用Python编写的shell脚本(当然grep .
实际上是一个更复杂的命令):
#!/bin/bash
(cat somefile 2>/dev/null || (echo 'somefile not found'; cat logfile)) \
| grep .
我尝试了这个(无论如何都缺少相当于cat logfile
):
#!/usr/bin/env python
import StringIO
import subprocess
try:
myfile = open('somefile')
except:
myfile = StringIO.StringIO('somefile not found')
subprocess.call(['grep', '.'], stdin = myfile)
但我收到错误AttributeError: StringIO instance has no attribute 'fileno'
。
我知道我应该使用subprocess.communicate()
代替StringIO将字符串发送到grep
进程,但我不知道如何混合字符串和文件。
答案 0 :(得分:9)
p = subprocess.Popen(['grep', '...'], stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
output, output_err = p.communicate(myfile.read())
答案 1 :(得分:4)
不要使用裸except
,它可能会抓得太多。在Python 3中:
#!/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()