2014-02-10 11 views
1

파일을 여는 데 특별히 with open 문을 사용해야합니다. 몇 백 개의 파일을 함께 열고 K- 방향 병합을 사용하여 병합해야하기 때문입니다. 나는 K가 낮게 유지되어야한다는 것이 이상적이지만, 나는이 문제를 예견하지 못했다."open with"문을 사용하여 여러 파일 (미리 알려지지 않은 파일 수)을 어떻게 열 수 있습니까?

마감 기한이 만료되어 처음부터 시작하는 옵션이 없습니다. 그래서이 시점에서 필자는 파일의 전체/거대한 부분을 메모리에 저장하지 않는 매우 빠른 I/O가 필요합니다. 왜냐하면 수백 개의 파일이 있기 때문에 각각 ~ 10MB입니다. K 웨이 병합을 위해 한 번에 한 줄씩 읽어야합니다. 현재 메모리 사용량을 줄이는 것이 내 주된 목표입니다.

나는 with open이 가장 효율적인 기술이라는 것을 알았지 만 open 모든 파일을 단일 with open 문에 함께 표시하는 방법을 이해할 수 없습니다. 실례합니다. 초심자의 무지!

업데이트 :이 문제가 해결되었습니다. 문제는 파일을 어떻게 열어 놓는 것이 아니라는 것이 밝혀졌습니다. 과도한 메모리 사용은 비효율적 인 가비지 수집으로 인한 것임을 알게되었습니다. 나는 with open을 전혀 사용하지 않았다. 나는 보통 f=open()f.close()을 사용했다. 가비지 콜렉션이 저장되었습니다.

+2

''열린 상태 '는'f = open() ... close (f)'보다 더 효율적이라고 생각하지 않습니다. 그것은 더 편리하다고 생각되지만, 그것은 당신의 상황에서 그렇지 않은 것처럼 들립니다. 파일 묶음을 열어 파일 개체를 목록에 보관할 수 있습니다. –

+3

'with' 문은 효율성과 아무런 관련이 없습니다. 예외가 발생하더라도 암시 적으로 파일이 닫힐 것입니다. @MarkkuK에 따르면 파일 객체에 대한 참조를 목록에 저장 한 다음 끝에 수동으로 닫고 try-finally 블록을 사용하여 오류가 발생하더라도 파일이 닫혀 있는지 확인할 수 있습니다. –

+0

빠른 응답을 보내 주셔서 감사합니다. 몇 백개의 파일을 열어도 메모리 사용량이 그렇게 높지 않을 수있는 대체 방법을 제안 할 수 있습니까? 이 파일들에서 한 번에 한 줄씩 만 필요하기 때문에 버퍼에있는 파일의 상당 부분을로드하지 않는 기술을 사용하면 도움이 될 것이라고 생각합니다. –

답변

1
with open(...) as f: 
    # do stuff 

가 귀하의 경우에는

f = open(...) 
# do stuff 
f.close() 

에 대략 번역, 나는 with open 구문을 사용하지 않을 것입니다. 당신은 파일 이름의 목록이있는 경우, 다음 파일 이름의 목록을 허용 당신이 정말로 with open 구문을 사용하려면

filenames = os.listdir(file_directory) 
open_files = map(open, filenames) 
# do stuff 
for f in open_files: 
    f.close() 

, 당신은 당신의 자신의 상황에 맞는 관리를 할 수 같은 것을 할

class MultipleFileManager(object): 
    def __init__(self, files): 
     self.files = files 

    def __enter__(self): 
     self.open_files = map(open, self.files) 
     return self.open_files 

    def __exit__(self): 
     for f in self.open_files: 
      f.close() 

그리고 다음과 같이 사용하십시오 :

filenames = os.listdir(file_directory) 
with MulitpleFileManager(filenames) as files: 
    for f in files: 
     # do stuff 

이 경우 컨텍스트 관리자를 사용하는 유일한 이점은 파일을 닫지 않아도된다는 것입니다. 그러나 수동으로 파일을 닫는 데는 아무런 문제가 없습니다. 그리고 os는 프로그램이 종료 될 때 리소스를 회수합니다.

+0

왜 파일을 닫으려고 '없음'목록을 만드는 중입니까? –

+0

@AshwiniChaudhary Nones 목록에 어떤 의미가 있습니까? –

+0

'map (lambda x : x.close(), self.open_files)' –

3

내장 된 contextmanger 함수 데코레이터를 사용하여 문서를 설명 할 때 "with 문 컨텍스트 관리자의 팩토리 함수"를 정의하면이 문제를 처리하는 데 비교적 쉽게 자신의 컨텍스트 관리자를 작성할 수 있습니다. 예를 들면 :

from contextlib import contextmanager 

@contextmanager 
def multi_file_manager(files, mode='rt'): 
    """ Open multiple files and make sure they all get closed. """ 
    files = [open(file, mode) for file in files] 
    yield files 
    for file in files: 
     file.close() 

filenames = 'file1', 'file2', 'file3' 

with multi_file_manager(filenames) as files: 
    a = files[0].readline() 
    b = files[2].readline() 
     ... 
0

하지 않는 솔루션은 2.7, 나는주의해야하지만 잘 때 얻을이 제대로 (놀라 울 정도로 어려운 작업을 수행하는 데 사용할 수있는 하나의 좋은 3.3 이상에 대한 올바른 솔루션, contextlib.ExitStack가있다 open 어떤 것인가가 그 시점 이전에 결정 론적으로 정리됩니다 성공한 open의 모두 실패 할 경우,

from contextlib import ExitStack 

with open('source_dataset.txt') as src_file, ExitStack() as stack: 
    files = [stack.enter_context(open(fname, 'w')) for fname in fname_list] 
    ... do stuff with src_file and the values in files ... 
... src_file and all elements in stack cleaned up on block exit ... 

중요한; 당신은 정중하게 자신의) 및 롤 대부분의 순진한 솔루션은 결국 가비지 컬렉터에 의지하고, 수집 할 오브젝트가없는 곳에서 잠금을 해제하지 못하는 잠금 수집과 같은 경우에 정리하지 못합니다.

이 질문은 파이썬 버전을 지정하지 않은 duplicate의 "원본"으로 표시되었으므로 여기에 게시하십시오.