2015-01-21 6 views
2

시나리오 : BZIP2으로 압축 된 PCAP 파일을 tcpdump으로 구문 분석하고 결과를 파이썬 2.7 내에서 한 줄씩 나열하고 싶습니다.BZ2를 Python 2.7에서 Popen stdin으로 직접 압축 해제하는 방법은 무엇입니까?

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() 

이의 문제가 Popenstdin 매개 변수가 실제 파일 핸들을 기대하고이 예외가 발생한다는 것입니다 :

AttributeError를 'BZ2 여기 내 머리 위로 떨어져 해낸거야 .BZ2File '객체에는'fileno '속성이 없습니다.

나는 이것을 2 단계 프로세스로 쉽게 만들 수 있지만 중간 임시 파일을 피하고 싶습니다.

생각이나 제안?

+0

를 아주 옆에서 '(tcpdump ','-l -n -s 0 -r -'))'는'tcpdump '와 동일하다. -l -n -s 0 -r - "', 명령 행에서도 작동하지 않습니다. 서로 관련이없는 모든 옵션을 하나의 큰 단일 인수로 전달할 수는 없습니다. –

+0

@CharlesDuffy 고맙습니다 - 해결되었습니다! –

답변

2

를 사용하여 두 개의 서로 다른는 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''): 
    ... 
1

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)