tempfile — 임시 파일과 디렉터리 생성
tempfile — 임시 파일과 디렉터리 생성
이 모듈은 임시 파일과 디렉터리를 만들어요. 지원되는 모든 플랫폼에서 동작하죠. TemporaryFile, NamedTemporaryFile, TemporaryDirectory, SpooledTemporaryFile은 자동 정리를 제공하고 컨텍스트 매니저로도 쓸 수 있는 고수준 인터페이스예요. mkstemp()와 mkdtemp()는 수동 정리가 필요한 저수준 함수고요.
사용자가 호출할 수 있는 모든 함수와 생성자는 임시 파일·디렉터리의 위치와 이름을 직접 제어할 수 있는 추가 인자를 받아요. 이 모듈이 쓰는 파일 이름에는 무작위 문자 문자열이 포함되어, 공유 임시 디렉터리에서도 안전하게 파일을 만들 수 있게 해줘요. 하위 호환성을 유지하기 위해 인자 순서가 좀 이상해요. 명확성을 위해 키워드 인자를 쓰는 걸 권장해요.
출처: Python 표준 라이브러리
본문
tempfile.TemporaryFile(mode='w+b', buffering=-1, encoding=None, newline=None, suffix=None, prefix=None, dir=None, *, errors=None) — 임시 저장 영역으로 쓰일 수 있는 파일류 객체를 반환해요. 파일은 mkstemp()와 같은 규칙으로 안전하게 생성돼요. 닫자마자 파괴돼요(객체가 가비지 컬렉션될 때의 암시적 닫기 포함). Unix에서 파일의 디렉터리 항목은 아예 생성되지 않거나 파일 생성 직후 제거돼요. 다른 플랫폼은 이것을 지원하지 않아요. 이 함수로 만든 임시 파일이 파일 시스템에서 보이는 이름을 갖거나 갖지 않을 것이라고 여러분의 코드는 믿으면 안 돼요.
결과 객체는 컨텍스트 매니저로 쓸 수 있어요(Examples 참고). 컨텍스트가 끝나거나 파일 객체가 파괴되면 임시 파일이 파일 시스템에서 제거돼요.
mode 파라미터의 기본값은 'w+b'라서 만들어진 파일을 닫지 않고 읽고 쓸 수 있어요. 저장되는 데이터와 무관하게 모든 플랫폼에서 일관되게 동작하도록 이진 모드가 사용돼요. buffering, encoding, errors, newline은 open()에서처럼 해석돼요.
dir, prefix, suffix 파라미터는 mkstemp()와 같은 의미와 기본값을 가져요.
반환된 객체는 POSIX 플랫폼에서 진짜 파일 객체예요. 다른 플랫폼에서는 파일류 객체이고 그 file 속성이 밑에 깔린 진짜 파일 객체예요.
os.O_TMPFILE 플래그는 사용할 수 있고 동작한다면 사용돼요(Linux 전용, Linux 커널 3.11 이상 필요). Posix도 Cygwin도 아닌 플랫폼에서 TemporaryFile은 NamedTemporaryFile의 별칭이에요.
이 함수는 인자 fullpath로 감사 이벤트 tempfile.mkstemp를 발생시켜요. 버전 3.5에서 변경: os.O_TMPFILE 플래그를 사용할 수 있으면 이제 사용함. 버전 3.8에서 변경: errors 파라미터 추가.
tempfile.NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None, newline=None, suffix=None, prefix=None, dir=None, delete=True, *, errors=None, delete_on_close=True) — 이 함수는 TemporaryFile()과 정확히 똑같이 동작하지만 다음 차이점이 있어요:
- 이 함수는 파일 시스템에서 보이는 이름을 가지는 것이 보장된 파일을 반환해요.
- 명명된 파일을 관리하기 위해
TemporaryFile()의 파라미터를delete와delete_on_close파라미터로 확장해, 명명된 파일이 자동으로 삭제될지 어떻게 삭제될지 결정해요.
반환된 객체는 항상 파일류 객체이고 그 file 속성이 밑에 깔린 진짜 파일 객체예요. 이 파일류 객체는 일반 파일처럼 with 문에서 쓸 수 있어요. 임시 파일의 이름은 반환된 파일류 객체의 name 속성에서 가져올 수 있어요. Unix에서는 TemporaryFile()과 달리 디렉터리 항목이 파일 생성 직후 언링크(unlink)되지 않아요.
delete가 참(기본값)이고 delete_on_close가 참(기본값)이면 파일은 닫는 즉시 삭제돼요. delete가 참이고 delete_on_close가 거짓이면 파일은 컨텍스트 매니저 종료 시에만, 또는 파일류 객체가 파이널라이즈될 때만 삭제돼요. 이 경우 삭제는 항상 보장되지는 않아요(object.__del__() 참고). delete가 거짓이면 delete_on_close의 값은 무시돼요.
따라서 임시 파일의 이름을 써서 닫은 뒤 다시 열려면, 닫을 때 파일을 삭제하지 않도록 하거나(delete 파라미터를 거짓으로 설정), 임시 파일이 with 문에서 생성되는 경우 delete_on_close 파라미터를 거짓으로 설정하세요. 후자의 방법이 컨텍스트 매니저 종료 시 임시 파일의 자동 정리를 도와주므로 권장돼요.
아직 열려 있는 동안 이름으로 임시 파일을 다시 여는 것은 다음과 같이 동작해요:
- POSIX에서 파일은 항상 다시 열 수 있어요.
- Windows에서는 다음 조건 중 적어도 하나가 충족되는지 확인하세요:
delete가 거짓.- 추가 열기가 삭제 접근을 공유함(예:
O_TEMPORARY플래그로os.open()호출). delete가 참이지만delete_on_close가 거짓. 이 경우 삭제 접근을 공유하지 않는 추가 열기(예: 내장open()으로 생성)는 컨텍스트 매니저를 빠져나가기 전에 닫아야 해요. 그렇지 않으면 컨텍스트 매니저 종료 시의os.unlink()호출이PermissionError로 실패할 거예요.
Windows에서 delete_on_close가 거짓이고 사용자에게 삭제 접근이 없는 디렉터리에 파일이 생성되면, 컨텍스트 매니저 종료 시 os.unlink() 호출이 PermissionError로 실패해요. delete_on_close가 참이면 요청된 접근이 부여되지 않을 때 열기가 즉시 실패하므로 그런 일이 없어요.
POSIX(에서만) SIGKILL로 갑자기 종료된 프로세스는 자신이 만든 NamedTemporaryFile을 자동으로 삭제할 수 없어요. 이 함수는 인자 fullpath로 감사 이벤트 tempfile.mkstemp를 발생시켜요. 버전 3.8에서 변경: errors 파라미터 추가. 버전 3.12에서 변경: delete_on_close 파라미터 추가.
class tempfile.SpooledTemporaryFile(max_size=0, mode='w+b', buffering=-1, encoding=None, newline=None, suffix=None, prefix=None, dir=None, *, errors=None) — 이 클래스는 TemporaryFile()과 정확히 똑같이 동작하지만, 파일 크기가 max_size를 초과하거나 파일의 fileno() 메서드가 호출될 때까지 데이터가 메모리에 스풀(spool)되고, 그 시점에 내용이 디스크에 쓰여 TemporaryFile()처럼 진행돼요.
결과 파일에는 rollover() 메서드 하나가 추가로 있어요. 이 메서드는 크기와 무관하게 파일을 온디스크 파일로 롤오버하게 해요.
반환된 객체는 파일류 객체이고 그 _file 속성은 (이진 모드인지 텍스트 모드인지에 따라) io.BytesIO 또는 io.TextIOWrapper 객체이거나, rollover()가 호출되었는지에 따라 진짜 파일 객체예요. 이 파일류 객체는 일반 파일처럼 with 문에서 쓸 수 있어요. 버전 3.3에서 변경: truncate 메서드가 size 인자를 받음. 버전 3.8에서 변경: errors 파라미터 추가. 버전 3.11에서 변경: io.BufferedIOBase와 io.TextIOBase 추상 베이스 클래스를 완전히 구현(이진/텍스트 모드에 따라).
class tempfile.TemporaryDirectory(suffix=None, prefix=None, dir=None, ignore_cleanup_errors=False, *, delete=True) — 이 클래스는 mkdtemp()와 같은 규칙으로 임시 디렉터리를 안전하게 만들어요. 결과 객체는 컨텍스트 매니저로 쓸 수 있어요(Examples 참고). 컨텍스트가 끝나거나 임시 디렉터리 객체가 파괴되면 새로 만든 임시 디렉터리와 그 모든 내용이 파일 시스템에서 제거돼요.
name— 디렉터리 이름은 반환된 객체의name속성에서 가져올 수 있어요. 반환된 객체를 컨텍스트 매니저로 쓸 때,with문에as절이 있으면name이 그 대상에 할당돼요.cleanup()—cleanup()메서드를 호출해 명시적으로 디렉터리를 정리할 수 있어요.ignore_cleanup_errors가 참이면 명시적 또는 암시적 정리 중에 처리되지 않은 예외(Windows에서 열린 파일을 제거할 때의PermissionError같은)가 무시되고, 남은 제거 가능한 항목을 "최선 노력(best-effort)" 기준으로 삭제해요. 그렇지 않으면 정리가 발생하는 어떤 컨텍스트에서든 오류가 발생돼요(cleanup()호출, 컨텍스트 매니저 종료, 객체 가비지 컬렉션, 인터프리터 종료 중).
delete 파라미터는 컨텍스트를 빠져나갈 때 디렉터리 트리의 정리를 비활성화하는 데 쓸 수 있어요. 컨텍스트 매니저가 컨텍스트를 빠져나갈 때 취해지는 동작을 비활성화하는 게 이상해 보일 수 있지만, 디버깅 중이거나 정리 동작을 다른 로직에 따라 조건부로 만들 필요가 있을 때 유용해요. 이 함수는 인자 fullpath로 감사 이벤트 tempfile.mkdtemp를 발생시켜요. (버전 3.2에 추가됨. 버전 3.10에서 변경: ignore_cleanup_errors 파라미터 추가. 버전 3.12에서 변경: delete 파라미터 추가.)
tempfile.mkstemp(suffix=None, prefix=None, dir=None, text=False) — 가능한 한 가장 안전한 방식으로 임시 파일을 만들어요. 플랫폼이 os.open()의 os.O_EXCL 플래그를 제대로 구현한다고 가정하면 파일 생성에 경쟁 조건(race condition)이 없어요. 파일은 생성 사용자 ID만 읽고 쓸 수 있어요. 플랫폼이 파일이 실행 가능한지 권한 비트로 나타내면 파일은 누구에게도 실행 불가능해요. 파일 디스크립터는 자식 프로세스에 상속되지 않아요.
TemporaryFile()과 달리 mkstemp() 사용자는 파일 디스크립터를 닫고(예: os.close()) 임시 파일을 삭제할(예: os.remove()) 책임이 있어요.
suffix가 None이 아니면 파일 이름이 그 접미사로 끝나고, 아니면 접미사가 없어요. mkstemp()는 파일 이름과 접미사 사이에 점을 넣지 않아요. 필요하면 suffix의 시작에 점을 넣으세요. prefix가 None이 아니면 파일 이름이 그 접두사로 시작하고, 아니면 기본 접두사가 사용돼요. 기본값은 gettempprefix() 또는 gettempprefixb()의 반환값이에요. dir이 None이 아니면 그 디렉터리에 파일이 만들어지고, 아니면 기본 디렉터리가 사용돼요. 기본 디렉터리는 플랫폼별 목록에서 선택되지만, 응용 사용자는 TMPDIR, TEMP, TMP 환경 변수를 설정해 디렉터리 위치를 제어할 수 있어요. 따라서 생성된 파일 이름이 os.popen()으로 외부 명령에 전달할 때 따옴표가 필요 없는 것 같은 좋은 성질을 가질 거라는 보장은 없어요.
suffix, prefix, dir 중 어떤 것이 None이 아니면 모두 같은 타입이어야 해요. bytes라면 반환된 이름도 str 대신 bytes가 돼요. 그 외에는 기본 동작으로 bytes 반환 값을 강제하려면 suffix=b''를 전달하세요. text가 지정되고 참이면 파일이 텍스트 모드로 열려요. 그렇지 않으면(기본값) 이진 모드로 열려요.
mkstemp()는 열린 파일의 OS-레벨 핸들( os.open()이 반환하는 것처럼)과 그 파일의 절대 경로명을 그 순서대로 담은 튜플을 반환해요. 이 함수는 인자 fullpath로 감사 이벤트 tempfile.mkstemp를 발생시켜요. 버전 3.5에서 변경: bytes 반환 값을 얻기 위해 suffix, prefix, dir을 bytes로 제공할 수 있음. 이전에는 str만 허용됐어요. suffix와 prefix가 이제 None을 받고 기본값으로 None을 써서 적절한 기본값이 사용되게 함. 버전 3.6에서 변경: dir 파라미터가 path-like 객체를 받음.
tempfile.mkdtemp(suffix=None, prefix=None, dir=None) — 가능한 한 가장 안전한 방식으로 임시 디렉터리를 만들어요. 디렉터리 생성에 경쟁 조건이 없어요. 디렉터리는 생성 사용자 ID만 읽고, 쓰고, 검색할 수 있어요. mkdtemp() 사용자는 다 쓴 뒤 임시 디렉터리와 그 내용을 삭제할 책임이 있어요. prefix, suffix, dir 인자는 mkstemp()와 같아요. mkdtemp()는 새 디렉터리의 절대 경로명을 반환해요. 이 함수는 인자 fullpath로 감사 이벤트 tempfile.mkdtemp를 발생시켜요. 버전 3.5에서 변경: bytes 반환 값을 얻기 위해 suffix, prefix, dir을 bytes로 제공할 수 있음. 버전 3.6에서 변경: dir 파라미터가 path-like 객체를 받음. 버전 3.12에서 변경: mkdtemp()가 dir이 상대 경로여도 이제 항상 절대 경로를 반환함.
tempfile.gettempdir() — 임시 파일에 쓰이는 디렉터리 이름을 반환해요. 이것이 이 모듈의 모든 함수에 대한 dir 인자의 기본값을 정의해요. Python은 표준 디렉터리 목록을 검색해 호출 사용자가 파일을 만들 수 있는 디렉터리를 찾아요. 목록은 다음과 같아요:
TMPDIR환경 변수가 가리키는 디렉터리.TEMP환경 변수가 가리키는 디렉터리.TMP환경 변수가 가리키는 디렉터리.- 플랫폼별 위치:
- Windows:
%USERPROFILE%\AppData\Local\Temp,%SYSTEMROOT%\Temp,C:\TEMP,C:\TMP,\TEMP,\TMP순서. - 다른 모든 플랫폼:
/tmp,/var/tmp,/usr/tmp순서.
- Windows:
- 마지막 수단으로 현재 작업 디렉터리.
이 검색 결과는 캐시돼요(아래 tempdir 설명 참고). 버전 3.10에서 변경: 항상 str을 반환. 이전에는 None이 아닌 한 타입과 무관하게 어떤 tempdir 값이든 반환했어요.
tempfile.gettempdirb() — gettempdir()과 같지만 반환 값이 bytes예요. (버전 3.5에 추가됨.)
tempfile.gettempprefix() — 임시 파일을 만드는 데 쓰이는 파일 이름 접두사를 반환해요. 디렉터리 구성 요소는 포함하지 않아요.
tempfile.gettempprefixb() — gettempprefix()과 같지만 반환 값이 bytes예요. (버전 3.5에 추가됨.)
모듈은 gettempdir()이 반환하는 임시 파일 디렉터리 이름을 저장하는 전역 변수를 사용해요. 그것을 직접 설정해 선택 과정을 덮어쓸 수 있지만 권장되진 않아요. 이 모듈의 모든 함수는 디렉터리를 지정할 수 있는 dir 인자를 받아요. 전역 API 동작을 바꿔 다른 예상치 못한 코드를 놀라게 하지 않는 권장 접근 방식이에요.
tempfile.tempdir — None이 아닌 값으로 설정되면 이 변수가 이 모듈에 정의된 함수들의 dir 인자 기본값을 정의해요(그 타입 bytes 또는 str 포함). path-like 객체일 수는 없어요. gettempprefix()를 제외한 위 함수 중 하나를 호출할 때 tempdir이 None(기본값)이면 gettempdir()에 설명된 알고리즘에 따라 초기화돼요.
참고 —
tempdir을 bytes 값으로 설정하면 좀 불쾌한 부작용이 있어요. 명시적인prefix,suffix,dir인자(타입 str)가 제공되지 않으면mkstemp()와mkdtemp()의 전역 기본 반환 타입이 bytes로 바뀌죠. 이것을 기대하거나 의존하는 코드를 쓰지 마세요. 이 어색한 동작은 과거 구현과의 호환성을 위해 유지돼요.
예제
tempfile 모듈의 일반적인 사용 예시들이에요:
>>> import tempfile
# create a temporary file and write some data to it
>>> fp = tempfile.TemporaryFile()
>>> fp.write(b'Hello world!')
# read data from file
>>> fp.seek(0)
>>> fp.read()
b'Hello world!'
# close the file, it will be removed
>>> fp.close()
# create a temporary file using a context manager
>>> with tempfile.TemporaryFile() as fp:
... fp.write(b'Hello world!')
... fp.seek(0)
... fp.read()
b'Hello world!'
>>>
# file is now closed and removed
# create a temporary file using a context manager
# close the file, use the name to open the file again
>>> with tempfile.NamedTemporaryFile(delete_on_close=False) as fp:
... fp.write(b'Hello world!')
... fp.close()
... # the file is closed, but not removed
... # open the file again by using its name
... with open(fp.name, mode='rb') as f:
... f.read()
b'Hello world!'
>>>
# file is now removed
# create a temporary directory using the context manager
>>> with tempfile.TemporaryDirectory() as tmpdirname:
... print('created temporary directory', tmpdirname)
>>>
# directory and contents have been removed
폐기된 함수와 변수
임시 파일을 만드는 역사적인 방식은 먼저 mktemp() 함수로 파일 이름을 생성하고 그 이름으로 파일을 만드는 거였어요. 안타깝게도 이것은 안전하지 않아요. mktemp() 호출과 그 뒤 첫 번째 프로세스가 파일을 만들려는 시도 사이에 다른 프로세스가 그 이름의 파일을 만들 수 있기 때문이죠. 해결책은 두 단계를 결합해 파일을 즉시 만드는 거예요. 이 접근을 mkstemp()와 위에서 설명한 다른 함수들이 사용해요.
tempfile.mktemp(suffix='', prefix='tmp', dir=None) — 버전 2.3부터 폐기: 대신 mkstemp() 사용. 호출 시점에 존재하지 않았던 파일의 절대 경로명을 반환해요. prefix, suffix, dir 인자는 mkstemp()의 것과 비슷하지만, bytes 파일 이름, suffix=None, prefix=None은 지원되지 않아요.
경고 — 이 함수를 쓰면 프로그램에 보안 구멍이 생길 수 있어요. 이 함수가 반환하는 파일 이름으로 무엇이든 하려고 할 즈음에는, 다른 누군가가 당신보다 먼저 그 이름을 써버렸을 수 있어요.
mktemp()의 사용은delete=False파라미터를 넘긴NamedTemporaryFile()로 쉽게 대체할 수 있어요:>>> f = NamedTemporaryFile(delete=False) >>> f.name '/tmp/tmptjujjt' >>> f.write(b"Hello World!\n") 13 >>> f.close() >>> os.unlink(f.name) >>> os.path.exists(f.name) False