我尝试编写上下文管理器,以便在处理后有条件地清理tempfile。简化为:
import os
from contextlib import contextmanager
from subprocess import Popen
from tempfile import NamedTemporaryFile
@contextmanager
def temp(cleanup=True):
tmp = NamedTemporaryFile(delete=False)
try:
yield tmp
finally:
cleanup and os.remove(tmp.name)
with temp() as tmp:
tmp.write(b'Hi')
p = Popen(['cmd', '/c', 'type', tmp.name])
p.wait()
尝试此脚本会引发:
Traceback (most recent call last):
File "C:\temp\test.py", line 18, in <module>
p.wait()
File "C:\Python35\lib\contextlib.py", line 66, in __exit__
next(self.gen)
File "C:\temp\test.py", line 13, in temp
cleanup and os.remove(tmp.name)
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'C:\\Temp\\tmp79su99sg'
我希望在语句循环结束时释放tempfile,而显然不是。
答案 0 :(得分:3)
当您尝试删除文件时,您的文件确实已打开。 在删除文件之前,您必须先关闭该文件:
@contextmanager
def temp(cleanup=True):
tmp = NamedTemporaryFile(delete=False)
try:
yield tmp
finally:
tmp.close() #closes the file, so we can right remove it
cleanup and os.remove(tmp.name)
另一个选择是使用context-manager包装文件对象:
@contextmanager
def temp(cleanup=True):
tmp = NamedTemporaryFile(delete=False)
try:
with tmp:
yield tmp
finally:
cleanup and os.remove(tmp.name)
答案 1 :(得分:3)
您可以将NamedTemporaryFile用作上下文管理器:
from tempfile import NamedTemporaryFile
with NamedTemporaryFile() as tmp:
tmp.write(b'Hi')
p = Popen(['cmd', '/c', 'type', tmp.name])
p.wait()
# Here the file is closed and thus deleted