2010-03-30 5 views
10

필자는 프로그램 과정에서 열리고 닫히는 명명 된 임시 파일을 만들어야하는 Python 프로그램이 있으며 프로그램이 끝날 때 삭제해야합니다. Windows에서 이름이 지정된 임시 파일을 어떻게 만들 수 있습니까?

  • TemporaryFile

    가 보이는 이름
  • NamedTemporaryFile이없는 파일 - 류의 객체를 생성 : 불행하게도, tempfile의 옵션 중 어느 것도 제대로 작동하지 않습니다. 파일 이름이 필요합니다. 반환하는 개체를 닫으려고했는데 (delete = False 설정 후) 나중에 파일을 열려고 할 때 스트림 오류가 발생합니다.
  • SpooledTemporaryFile 표시 이름이 없습니다.
  • mkstemp은 열린 파일 개체와 이름을 모두 반환합니다. 프로그램이
  • mktemp
  • 파일 이름을 반환 종료하지만, 프로그램이 내가 내 mktemp 1를 사용하려고했습니다

을 종료 할 때 삭제 된 파일을 보장하지 않는 경우이 파일이 삭제됩니다 보장하지 않습니다 컨텍스트 관리자 :

def get_temp_file(suffix): 
    class TempFile(object): 
     def __init__(self): 
      self.name = tempfile.mktemp(suffix = '.test') 

     def __enter__(self): 
      return self 

     def __exit__(self, ex_type, ex_value, ex_tb): 
      if os.path.exists(self.name): 
       try: 
        os.remove(self.name) 
       except: 
        print sys.exc_info() 

    return TempFile() 

...하지만 저에게 WindowsError(32, 'The process cannot access the file because it is being used by another process')을 제공합니다. 파일 이름은 프로세스가 내 프로그램을 생성하는 데 사용되며, 나가기 전에 프로세스가 끝났음에도 불구하고 내 제어에서 경쟁 조건이있는 것처럼 보입니다.

이 문제를 해결하는 가장 좋은 방법은 무엇입니까?

여기서는 보안에 대해 걱정할 필요가 없습니다. 이것은 테스트 모듈의 일부이기 때문에 가장 사악한 누군가가 할 수있는 것은 우리의 단위 테스트가 허위로 실패하는 것입니다. 공포!

+0

이 보안 문제들이 임시 파일을 예를 들어 중요한에 심볼릭 링크 (에 생성되어 전체 시스템에 영향을 미치는, 임시 파일을 사용하여 프로그램에 영향을 미치지 않습니다 파일을 만든 후). –

+0

임시 파일을 여는 모든 파일 객체가 제대로 닫혔습니까? – user49117

+0

파일 이름은 Popen()을 통해 Windows 프로세스에 전달되며,이 파일을 끝내면 .sysin, .sysout 및 .syserr 스트림에서 .flush()를 호출 한 다음 .wait()를 호출합니다. 방법. 그게 ContextManager에 싸여있어, 나는 그것이 불려 졌음을 확신한다. 내가 뭘 할 수 있는지 잘 모르겠다. –

답변

1

보안에 신경 쓰지 않는다면 무엇이 잘못 되었습니까?

tmpfile_name = tempfile.mktemp() 
# do stuff 
os.unlink(tmpfile_name) 

너는 이것을 과도하게 노력하고있을 수도 있습니다. 프로그램이 종료 될 때이 파일이 항상 제거되도록하려는 경우 try/finallymain() 실행을 래핑 할 수 있습니다. 계속 간단하게!

+2

os.unlink는 문서에 따라 os.remove와 동일합니다. 그렇다면 동일한 예외가 발생합니다. 맞습니까? –

2

업로드 된 파일을 csv 모듈을 사용하여 열린 임시 파일에 저장해야 할 때와 똑같은 문제가 발생했습니다. 가장 짜증나는 것은 WindowsError의 파일 이름이 임시 파일을 가리키고 있지만 업로드 파일 내용을 StringIO 버퍼에 저장하고 버퍼 데이터를 임시 파일로 푸시하는 것이 문제를 해결 한 것입니다. 필자의 필요에 따라 업로드 된 파일이 항상 메모리에 들어 있기 때문에 충분했습니다.

문제는 Apache의 CGI를 통해 스크립트가있는 파일을 업로드 한 경우에만 문제가 재현되지 않는 콘솔에서 비슷한 스크립트를 실행했을 때 발생했습니다.

4

오늘과 비슷한 것이 필요했고 결국 내 것을 작성했습니다. atexit.register()를 사용하여 프로그램이 종료 될 때 파일을 제거하는 함수 콜백을 등록합니다.

이 코딩 표준은 일반적인 파이썬 코딩 표준 (use_underscores 대신 camelCase)과 약간 다릅니다. 당연히 조정하십시오.

def temporaryFilename(prefix=None, suffix='tmp', dir=None, text=False, removeOnExit=True): 
    """Returns a temporary filename that, like mkstemp(3), will be secure in 
    its creation. The file will be closed immediately after it's created, so 
    you are expected to open it afterwards to do what you wish. The file 
    will be removed on exit unless you pass removeOnExit=False. (You'd think 
    that amongst the myriad of methods in the tempfile module, there'd be 
    something like this, right? Nope.)""" 

    if prefix is None: 
     prefix = "%s_%d_" % (os.path.basename(sys.argv[0]), os.getpid()) 

    (fileHandle, path) = tempfile.mkstemp(prefix=prefix, suffix=suffix, dir=dir, text=text) 
    os.close(fileHandle) 

    def removeFile(path): 
     os.remove(path) 
     logging.debug('temporaryFilename: rm -f %s' % path) 

    if removeOnExit: 
     atexit.register(removeFile, path) 

    return path 

슈퍼 기본 테스트 코드 :

path = temporaryFilename(suffix='.log') 
print path 
writeFileObject = open(path, 'w') 
print >> writeFileObject, 'yay!' 
writeFileObject.close() 

readFileObject = open(path, 'r') 
print readFileObject.readlines() 
readFileObject.close() 
관련 문제