如何在Python 2.7 中将BZ2 直接解压到Popen stdin 中?
How to decompress BZ2 directly into Popen stdin in Python 2.7?
场景:PCAP
用 BZIP2
压缩的文件,我想用 tcpdump
解析并在 Python 2.7 中逐行列出结果。这是我突然想到的:
def tcpdump(filename):
import subprocess
import bz2
p = subprocess.Popen(
('tcpdump', '-lnr', '-s', '0', '-'),
stdin=bz2.BZ2File(filename),
stdout=subprocess.PIPE)
try:
for row in p.stdout:
yield row.rstrip()
except KeyboardInterrupt:
p.terminate()
这个问题是 Popen
的 stdin
参数需要一个实际的文件句柄并抛出这个异常:
AttributeError: 'bz2.BZ2File' 对象没有属性 'fileno'
我可以很容易地将其分为两步,但我想避免使用中间临时文件。
想法或建议?
使用两个不同的 Popen 对象:
p1 = subprocess.Popen(['bunzip2', '-c', filename],
stdout=subprocess.PIPE)
p2 = subprocess.Popen(['tcpdump', '-lnr', '-s', '0', '-'],
stdin=p1.stdout,
stdout=subprocess.PIPE)
p1.stdout.close()
for row in iter(p2.stdout.readline, b''):
...
为避免bunzip2
依赖,您可以手动输入:
import subprocess
import threading
from contextlib import closing
p = subprocess.Popen(['tcpdump', '-lnr', '-s', '0', '-'],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, bufsize=-1)
threading.Thread(target=pump, args=[filename, p.stdin]).start()
with closing(p.stdout):
for line in iter(p.stdout.readline, b''):
print line,
p.wait()
其中 pump()
是:
from shutil import copyfileobj
def pump(filename, pipe):
"""Decompress *filename* and write it to *pipe*."""
with closing(pipe), bz2.BZ2File(filename) as input_file:
copyfileobj(input_file, pipe)
场景:PCAP
用 BZIP2
压缩的文件,我想用 tcpdump
解析并在 Python 2.7 中逐行列出结果。这是我突然想到的:
def tcpdump(filename):
import subprocess
import bz2
p = subprocess.Popen(
('tcpdump', '-lnr', '-s', '0', '-'),
stdin=bz2.BZ2File(filename),
stdout=subprocess.PIPE)
try:
for row in p.stdout:
yield row.rstrip()
except KeyboardInterrupt:
p.terminate()
这个问题是 Popen
的 stdin
参数需要一个实际的文件句柄并抛出这个异常:
AttributeError: 'bz2.BZ2File' 对象没有属性 'fileno'
我可以很容易地将其分为两步,但我想避免使用中间临时文件。
想法或建议?
使用两个不同的 Popen 对象:
p1 = subprocess.Popen(['bunzip2', '-c', filename],
stdout=subprocess.PIPE)
p2 = subprocess.Popen(['tcpdump', '-lnr', '-s', '0', '-'],
stdin=p1.stdout,
stdout=subprocess.PIPE)
p1.stdout.close()
for row in iter(p2.stdout.readline, b''):
...
为避免bunzip2
依赖,您可以手动输入:
import subprocess
import threading
from contextlib import closing
p = subprocess.Popen(['tcpdump', '-lnr', '-s', '0', '-'],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, bufsize=-1)
threading.Thread(target=pump, args=[filename, p.stdin]).start()
with closing(p.stdout):
for line in iter(p.stdout.readline, b''):
print line,
p.wait()
其中 pump()
是:
from shutil import copyfileobj
def pump(filename, pipe):
"""Decompress *filename* and write it to *pipe*."""
with closing(pipe), bz2.BZ2File(filename) as input_file:
copyfileobj(input_file, pipe)