2011-12-20 3 views
1

나는 어리석게 큰 텍스트 파일이 있다고 해봅시다. 내 파일이 ~ 500MB보다 커질 것이라고 생각하지는 않지만, 확장 성과 내 호기심 때문에 몇 권의 순서대로한다고 가정 해 봅시다.큰 텍스트 파일 (파이썬)을 읽고 쓰고 파싱하는 효율적인 방법

목표는 문장의 배열 ('?' '!' '.'과 모든 의도와 목적 ';'으로 구분)과 각 문장을 단어 배열로 매핑하는 것입니다. 몇 가지 통계 분석에 numpy를 사용하려고했습니다.

이 작업을 수행하는 가장 확장 성있는 방법은 무엇입니까?

추신 : 필자는 파일을 한 줄에 하나의 문장으로 다시 작성한다고 생각했지만 파일을 메모리에로드하려고 할 때 문제가 발생했습니다. 하나의 파일에서 데이터를 꺼내 조작하고 다른 곳으로 쓰는 해결책을 알고 있지만 디스크 메모리는 비효율적 인 것처럼 보입니다. 나도 알다시피, 대부분의 사람들은 10gig의 스크래치 공간을 요즘 사용하는 것에 대해 걱정하지 않을 것이지만, 파일의 척을 직접 편집해야하는 것처럼 보입니다.

+2

* 모든 집중적 인 목적 * 또는 * 모든 의도와 목적을 위해 *? – MattH

+0

sqllite와 같은 데이터베이스를 사용하지 않는 이유는 무엇입니까? – jterrace

+1

파일을 스트림으로 스캔하고 대신 카운트를 유지하는 것이 좋습니다. 파싱이 복잡 할 것 같지 않습니까? – fge

답변

5

첫 번째 생각은 스트림 파서를 사용하는 것입니다. 기본적으로 한 번에 파일을 읽고 통계 분석을 수행합니다. 일반적으로 HTML 및 XML과 같은 마크 업 언어를 사용하므로 파이썬 표준 라이브러리를 비롯하여 그 언어에 대한 많은 파서를 찾을 수 있습니다. 간단한 문장 파서는 여러분이 직접 작성할 수있는 것입니다.

import re, collections 
sentence_terminator = re.compile(r'(?<=[.!?;])\s*') 
class SentenceParser(object): 
    def __init__(self, filelike): 
     self.f = filelike 
     self.buffer = collections.deque(['']) 
    def next(self): 
     while len(self.buffer) < 2: 
      data = self.f.read(512) 
      if not data: 
       raise StopIteration() 
      self.buffer += sentence_terminator.split(self.buffer.pop() + data) 
     return self.buffer.popleft() 
    def __iter__(self): 
     return self 

이렇게하면 문장을 완성하는 데 필요한 파일의 데이터 만 읽습니다. 512 바이트 블록 단위로 읽으 므로 실제 파일의 크기에 관계없이 한 번에 메모리에있는 파일 내용을 킬로바이트 미만으로 유지하게됩니다.

스트림 파서 이후에 두 번째 생각은 memory map입니다. 그렇게하면 (아마도) 각 문장의 종결 자 다음에 개행 문자가 오는 공간을 통과 할 수 있습니다. 그 다음에 각 문장이 새로운 라인에서 시작하면 파일을 열어 readline() 또는 for 루프를 사용하여 한 줄씩 넘길 수 있습니다. 그러나 당신은 여전히 ​​여러 줄 문장에 대해 걱정해야합니다. 더하기 어떤 문장 종결자가 이 아니고이 아닌 공백 문자가 있다면, (다른 것을 대체하는 대신에) 개행 문자를 삽입해야하고 큰 파일에 대해 비효율적 일 수 있습니다.

관련 문제