2012-06-10 3 views
7

나는 임시 디렉토리로 작업하고있어 프로그램이 성공적으로 종료되었는지에 관계없이 프로그램이 닫힐 때 삭제되는지 확인하고자합니다. 나는 확실하지 않다 무엇 여기임시 디렉토리를 프로그램 종료시 삭제되도록 어떻게 관리합니까?

import shutil 
import tempfile 

class TempDir(str): 
    """ container for temporary directory. 
    Deletes directory when garbage collected/zero references """ 
    def __del__(self): 
     shutil.rmtree(self.__str__(), onerror=my_error_fn) 

dbdir = TempDir(tempfile.mkdtemp()) 

: 프로그램이 종료하는 경우 또는 내가 디렉토리를 작성 tempfile.mkdtemp를 사용하고 __del__ 명령에 디렉토리를 삭제 str의 서브 클래스로 만들어지는 문자열을 걸었습니다 KeyboardInterrupt가 발생하면 파이썬은 자동으로 모든 변수를 삭제/가비지 수집합니까? 그렇지 않다면 디렉토리가 삭제되는지 어떻게 확인할 수 있습니까?

관련 정보 creating destructor methods in Python. 오랫동안 TempDir 객체가 다른 것을 참조하지 않는 한, __del__을 사용하여 정상적으로 파괴되어야합니다.

+1

테스트했을 때 무엇을 발견 했습니까? Ctrl + C를 누를 때마다'__del__'이 실행됩니까? –

+0

좋아, 그냥 내 테스트의 결과를 추가 - 제안에 대단히 감사합니다 @ JoelCornett! –

+0

'__del__' 외에도'atexit' 모듈 사용을 고려하십시오. – martineau

답변

17

나는 __del__ 메서드를 사용하지 않을 것이고, 의미는 신뢰할 수 없으며 가비지 수집을 방해 할 수 있습니다. 컨텍스트 관리자를 사용하십시오 : __enter____exit__ 메서드를 정의하고 with 문에 개체를 사용하십시오. 그것은 분명합니다. 명백합니다. 걱정없이 작동 할 것입니다.

또는 컨텍스트 관리자를 만들 수있는 또 다른 방법 :

@contextlib.contextmanager 
def tempdir(prefix='tmp'): 
    """A context manager for creating and then deleting a temporary directory.""" 
    tmpdir = tempfile.mkdtemp(prefix=prefix) 
    try: 
     yield tmpdir 
    finally: 
     shutil.rmtree(tmpdir) 
+1

에 대한 질문 :이 파일을 생성하기 위해이 디렉토리를 사용하고 싶은데, (1) 프로그램이 끝났을 때 또는 (2) 디렉토리에있는 파일에 대한 모든 참조가 없어 졌을 때 (즉, 내 구현, TempDir 클래스에 대한 모든 참조도 사라질 것입니다.)이 형식으로 할 수 있습니까? –

+1

여기에 또 하나의 요점이 있습니다. 패키지를 사용하는 사람들이 파일을 추가/제거하고 임시 파일을 투명하게 처리해야 할 것입니다. 컨텍스트 관리자에게 적합하지 않은 것 같습니다. –

+0

Jeff, 맞습니다. 자원의 수명이 어휘 범위와 일치 할 때 컨텍스트 관리자가 좋습니다. 컨텍스트 관리자는 여전히 프로그램의 최상위 레벨에서 프로그램 종료를 처리하는 데 사용될 수 있지만 다른 오브젝트 참조는 명시 적으로 관리하여 디렉토리를 참조하는 파일을 처리 할 수 ​​있습니다. –

1

프로그램이 끝날 때만 (일반적으로와 같이) 모든 항목이 삭제됩니다.

설명하기 위해, 여기 내가 사용하는 코드는 다음과 같습니다

import tempfile 
import shutil 
import os 

class TempDir(str): 
    """ container for temporary directory. Deletes directory when garbage 
    collected/zero references """ 
    def __del__(self): 
     print "deleting temporary files in directory {}".format(self.__str__()) 
     shutil.rmtree(self.__str__(), onerror=delete_dir_handler) 

def delete_dir_handler(listdir_fn, dirname, exception): 
    try: 
     for fileobj in listdir_fn(dirname): 
      os.remove(fileobj) 
     os.removedirs(dirname) 
    except (AttributeError, OSError, TypeError): 
     print exception[1] 
     print "Sorry. Couldn't delete directory {}.".format(dirname) 
     raise 

test = TempDir(tempfile.mkdtemp()) 

그리고 출력 : 대화 형 모드로 실행하면 프로그램을 종료 할 때까지

$ python my_file.py 
deleting temporary files in directory /var/folders/A9/A9xrfjrXGsq9Cf0eD2jf0U+++TI/-Tmp-/tmpG3h1qD 

, 그것은 삭제되지 않습니다. 이 파일에 raw_input('') 줄을 추가하는 경우는 Ctrl-C를 키를 누르면

$ python -i my program 
>>> # pressed Ctrl-C here 
KeyboardInterrupt 
>>> # again, Ctrl-C 
KeyboardInterrupt 
>>> # Ctrl-D to exit 
deleting temporary files in directory /var/folders/A9/A9xrfjrXGsq9Cf0eD2jf0U+++TI/-Tmp-/tmpMBGt5n 

마지막으로,이 프로그램 종료와 정확히 같은 동작합니다.

7

내가 특정의 존재에 의존 패키지 테스트 스위트에 대한 비슷한 필요한 파일 구조를 (반 조롱). 많은 테스트 모듈을 통해 어떤 테스트가 어떤 순서로 실행되는지 또는 테스트 실행이 어떻게 종료 될지 항상 알 수는 없습니다.

응용 프로그램 종료시 __del__을 사용하면 내 경험에 신뢰할 수 없습니다. 컨텍스트 관리자를 사용하면 테스트 파일을 다시 작성해야 모든 내용이 멋지게 처리됩니다. 대신 atexit을 사용합니다. <package>.tests.__init__에서 나는 방금 추가 :

import atexit, shutil, tempfile 

test_area = tempfile.mkdtemp() 
atexit.register(shutil.rmtree, test_area) 

파이썬은 다음 출구에서 shutil.rmtree(test_area)를 호출합니다. 필요한 경우 오류 처리를위한 키워드 인수를 추가 할 수도 있습니다.

관련 문제