2014-10-28 2 views
0

이 작은 스크립트 파일을 읽는 정규식 각 라인을 일치 시키려고, 다른 파일에 일치하는 라인을 추가합니다 : 왜이 파이썬 스크립트가 파일에 갑자기 쓰는 걸까요?

regex = re.compile(r"<http://dbtropes.org/resource/Film/.*?> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://dbtropes.org/resource/Main/.*?> \.") 

with open("dbtropes-v2.nt", "a") as output, open("dbtropes.nt", "rb") as input: 
    for line in input.readlines(): 
     if re.findall(regex,line): 
      output.write(line) 

input.close() 
output.close() 

그러나, 스크립트는 갑자기 약 5 분 후에 중지됩니다. 터미널에 "프로세스가 중지되었습니다"라는 메시지가 표시되고 출력 파일이 비어있게됩니다.

입력 파일은 여기에서 다운로드 할 수 있습니다. http://dbtropes.org/static/dbtropes.zip 4.3Go n-triples 파일입니다.

내 코드에 문제가 있습니까? 다른 것입니까? 어떤 힌트 가이 하나에 감사하겠습니다!

+0

'top'을 사용하여 프로세스에서 사용중인 메모리 양을 확인하십시오. 그리고/또는 진행 상황 출력을 추가하십시오. –

+0

부수적으로, 일치하는 항목이 있는지를 확인하는 중이라면'findall'을 원하지 않을 것입니다. 첫 번째 검색 결과가 아니라 모든 검색 결과를 찾기 위해 성능에 큰 영향을 미치지는 않을 것입니다.하지만 도움이되지 않습니다. 개념적으로 약간 혼란 스럽기 때문에 그냥하지 않는 것이 좋습니다. – abarnert

+0

또한 패턴을 정규식 객체로 컴파일하려면 최상위 함수 ('re.findall (regex, line)')가 아닌 그 메소드 ('regex.findall (line)')를 사용하십시오. 성능 영향은 여기에서 더 작을 수 있습니다. 다시 한번 말하면 가독성에 관한 것입니다. (예를 들어 처음 3자를 무시하고 싶다는 말을하고 싶다면이 방법은 더욱 유연합니다. – abarnert

답변

7

메모리가 부족하여 중단되었습니다. input.readlines()은 줄 목록을 반환하기 전에 전체 파일을 메모리로 읽습니다.

대신에 input을 반복자로 사용하십시오. 한 번에 몇 줄만 읽고, 즉시 반환합니다.

이 작업을 수행하지 마십시오
for line in input.readlines(): 

이렇게 수행

for line in input: 

계정에 모든 사람의 조언을 촬영, 프로그램이된다 :

regex = re.compile(r"<http://dbtropes.org/resource/Film/.*?> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://dbtropes.org/resource/Main/.*?> \.") 

with open("dbtropes.nt", "rb") as input: 
    with open("dbtropes-v2.nt", "a") as output 
     for line in input: 
      if regex.search(line): 
       output.write(line) 
+0

예, 전체 파일을 한 번에 읽을 수 없습니다. –

+0

나를 이길. 파이썬에서조차도 충분한 데이터로 작업 할 때 컴퓨터를 사용하는 데 너무 많은 메모리를 사용할 수 있기 때문에 조심해야합니다. – Crispy

1

사용 for line in input보다전체 파일을 읽지 못하도록합니다.

사소한 점 : 컨텍스트 관리자로 파일을 열지 않아도 파일을 닫을 필요가 없습니다. 다음과 같이 청소기를 찾을 수 있습니다.

with open("dbtropes-v2.nt", "a") as output 
    with open("dbtropes.nt", "rb") as input: 
      for line in input: 
       if re.findall(regex,line): 
        output.write(line) 
+1

나는이 코드 샘플을 좋아한다. 출력을 열기 전에 입력을 열기 위해'with '문을 재정렬 할 수 있습니다. 그렇게하면 입력 파일이없는 경우 여분의 리소스가 할당되지 않으며 잘못된 출력 파일이 생성되지 않습니다. –

+0

이 컨텍스트에서 파일을 닫을 필요가없는 이유는 무엇입니까? 이전에 읽은 파일 (예 : http://stackoverflow.com/questions/5972277/write-not-working-in-python 참조)은 파일을 버퍼링하기 때문에 파일이 제대로 닫히지 않으면 파일이 전혀 쓰이지 않을 수도 있습니다. – kormak

+1

'with'가 자동적으로'.close()'를 호출하기 때문에 파일을 명시 적으로 닫을 필요는 없습니다.파일을 닫으려면 * 필요합니다. 그래서'with '를 사용했습니다. ['file.close()'] (https://docs.python.org/2/library/stdtypes.html#file.close)의 예제를 참조하십시오. –