2014-09-20 1 views
3

파이썬에서 새 파일을 열 수 없습니다. ls -l /proc/PID/fd으로 조사했을 때 나는 파이썬 프로세스를 위해 많은 파일을 열어 보았다. 내가 사용중인 모듈은 분명히 많은 파일을 열고 닫지 않은 것입니다.파일 식별자가 없을 때 파이썬에서 파일을 닫는 방법

파일을 연 모듈과 관련된 개체를 삭제하여 파일을 닫을 수 있기를 기대했지만 아무 일도 없었습니다.

는 또한 파일이 가비지 컬렉션 어딘가에 개체를 볼 것으로 예상했지만, 나는이 함께 열려있는 파일을 닮은 아무것도 보지 못했다 :

for obj in gc.get_objects(): 
    if hasattr(obj, 'read'): 
     print(obj) 

내가 파이썬을 종료 할 때 파일이 사라집니다.

+0

'ls'의 출력을 가질 수 있습니까? 얼마나 많은 파일을 말하고 있습니까? – Veedrac

+6

아마 어떤 백 채널을 통해 그들을 닫으려고해서는 안됩니다 ... 아마도 라이브러리의 버그 (또는 어떻게 사용하고있는 것일까?) 일 것입니다. 누수가 어디서 왔는지 파악하고 파일을 적절히 닫아야합니다. – FatalError

+0

요즘 파일을 여는 데 권장되는 방법은 'with fid : fid : ...'여야합니다. 이것은'with' 블록이 끝날 때 파일을 직접 닫아야합니다. 라이브러리에서 파일을 여는 방법에 대한 코드 스 니펫이 있습니까? –

답변

4

문제는 파일 설명자가 파이썬 개체와 관련없이 누수되고있는 것일 수 있습니다. 파이썬은 파이썬 객체와 관련이없는 실제 파일 디스크립터 (OS 자원)를 볼 방법이 없다. 파이썬 객체와 관련되어 있다면, 파이썬은 가비지 수집 될 때 파이썬을 닫을 것입니다. 또는 타사 라이브러리가 자체적으로 파일 설명자를 추적합니다.

일반 정수로 os.close을 사용하여 연관된 파일 설명자를 닫을 수 있습니다. 열려는 파일 설명자 (보통 stdin/stdout/stderr, 0, 1, 2 및 기타 다른 파일 설명자)를 알고있는 경우 0에서 65535 사이의 다른 모든 정수를 닫을 수 있습니다. /proc/<pid>/fd :

import os 

KEEP_FD = set([0, 1, 2]) 

for fd in os.listdir(os.path.join("/proc", str(os.getpid()), "fd")): 
    if int(fd) not in KEEP_FD: 
     try: 
      os.close(int(fd)) 
     except OSError: 
      pass 

이것은 상당히 악의적 인 해킹입니다. 더 나은 해결책은 타사 라이브러리를 수정하는 것입니다.

+1

나는'매우 악 '이라고 말할 것입니다. - 그다지 예쁘지는 않습니다. (효율은 6 라인을 제외하고는 6 라인입니다.) 해결책을 찾으려고 +1합니다. 정말로 문제는 라이브러리에 사용되는 것이지만. –

+0

예. 때로는 라이브러리를 제어 할 수없는 경우도 있습니다. 유스 케이스에 따라, 해당 라이브러리가 파일 디스크립터를 새고있는 곳을 파악하려고 시도하는 것은 거의 불가능할 수도있다. 어떤 도서관인지 모른 채 말하기는 어렵다. :-) –

+0

이 악의적 인 해킹은 지금까지 효과가 있습니다. 우리 애플리케이션에서 나는 if os.readlink (os.path.join (pathname, fd))를 추가했다. endswith ('ttf') :' –

관련 문제