重命名 Python 中的临时文件
Renaming temporary files in Python
我想执行以下操作。创建一个临时文件并处理它。如果成功,将其重命名为真实文件。如果失败,则删除该文件。
我尝试了以下方法:
with tempfile.NamedTemporaryFile(dir=os.getcwd()) as f:
f.write(b'foobar')
f.delete = False
f.flush()
os.rename(f.name, 'foobar')
但是,当我试图删除它时,我仍然得到一个异常,该文件不存在。我可能会使用 try-catch 来忽略此错误,但这会很丑陋并且也可能会忽略其他错误。或者我可以使用 mkstemp()
并自己管理删除,但这有一个问题,它 returns 是一个文件描述符而不是文件对象,而且我找不到从文件描述符。
这个问题有什么好的解决方法吗?
这可以通过 NamedTemporaryFile
class 来实现。关闭后,您可以将其移动到所需的 location/filename。为避免删除错误,您需要在移动前关闭文件。
from tempfile import NamedTemporaryFile
import shutil
with NamedTemporaryFile(delete=False) as tmp:
tmp.write(b'hi')
# move file to target location/name
shutil.move(tmp.name, 'target')
初始化的时候需要传delete=False
,后面设置f.delete = False
是不行的。在用这段代码编写后,我能够重命名它:
with tempfile.NamedTemporaryFile(dir=os.getcwd(), delete=False) as f:
f.write(b'foobar')
f.flush()
os.rename(f.name, 'foobar')
我查看了 Lib/tempfile.py 的代码以确认此行为。
当您调用 NamedTemporartyFile
时,它会初始化 returns 在同一文件中定义的 _TemporaryFileWrapper
class 的一个实例。看看这个class的__init__()
:
def __init__(self, file, name, delete=True):
self.file = file
self.name = name
self.delete = delete
self._closer = _TemporaryFileCloser(file, name, delete)
这里是 _TemporaryFileCloser
的 __init__()
class:
def __init__(self, file, name, delete=True):
self.file = file
self.name = name
self.delete = delete
当您退出 with 语句时,在关闭文件期间,将检查 _TemporaryFileCloser
的 self.delete
属性。当您执行 f.delete = False
时,您更改了 _TemporaryFileWrapper
class 的 self.delete
属性,而不是 _TemporaryFileCloser
class。因此,关闭行为不会改变,即使在开发人员方面看起来是这样。因此,您必须在 with
语句的初始化期间传递 delete=False
,就像我的代码示例中那样。
如果你还想修改行为,你可以访问self._closer
属性,但是它会有点难看。
with tempfile.NamedTemporaryFile(dir=os.getcwd()) as f:
f.write(b'foobar')
f.flush()
f._closer.delete = False
os.rename(f.name, 'foobar')
顺便说一句,我在 Windows 10 上对 Ubuntu WSL 执行了此操作。我不确定您使用的是哪个 OS,这可能会影响行为。
我想执行以下操作。创建一个临时文件并处理它。如果成功,将其重命名为真实文件。如果失败,则删除该文件。
我尝试了以下方法:
with tempfile.NamedTemporaryFile(dir=os.getcwd()) as f:
f.write(b'foobar')
f.delete = False
f.flush()
os.rename(f.name, 'foobar')
但是,当我试图删除它时,我仍然得到一个异常,该文件不存在。我可能会使用 try-catch 来忽略此错误,但这会很丑陋并且也可能会忽略其他错误。或者我可以使用 mkstemp()
并自己管理删除,但这有一个问题,它 returns 是一个文件描述符而不是文件对象,而且我找不到从文件描述符。
这个问题有什么好的解决方法吗?
这可以通过 NamedTemporaryFile
class 来实现。关闭后,您可以将其移动到所需的 location/filename。为避免删除错误,您需要在移动前关闭文件。
from tempfile import NamedTemporaryFile
import shutil
with NamedTemporaryFile(delete=False) as tmp:
tmp.write(b'hi')
# move file to target location/name
shutil.move(tmp.name, 'target')
初始化的时候需要传delete=False
,后面设置f.delete = False
是不行的。在用这段代码编写后,我能够重命名它:
with tempfile.NamedTemporaryFile(dir=os.getcwd(), delete=False) as f:
f.write(b'foobar')
f.flush()
os.rename(f.name, 'foobar')
我查看了 Lib/tempfile.py 的代码以确认此行为。
当您调用 NamedTemporartyFile
时,它会初始化 returns 在同一文件中定义的 _TemporaryFileWrapper
class 的一个实例。看看这个class的__init__()
:
def __init__(self, file, name, delete=True):
self.file = file
self.name = name
self.delete = delete
self._closer = _TemporaryFileCloser(file, name, delete)
这里是 _TemporaryFileCloser
的 __init__()
class:
def __init__(self, file, name, delete=True):
self.file = file
self.name = name
self.delete = delete
当您退出 with 语句时,在关闭文件期间,将检查 _TemporaryFileCloser
的 self.delete
属性。当您执行 f.delete = False
时,您更改了 _TemporaryFileWrapper
class 的 self.delete
属性,而不是 _TemporaryFileCloser
class。因此,关闭行为不会改变,即使在开发人员方面看起来是这样。因此,您必须在 with
语句的初始化期间传递 delete=False
,就像我的代码示例中那样。
如果你还想修改行为,你可以访问self._closer
属性,但是它会有点难看。
with tempfile.NamedTemporaryFile(dir=os.getcwd()) as f:
f.write(b'foobar')
f.flush()
f._closer.delete = False
os.rename(f.name, 'foobar')
顺便说一句,我在 Windows 10 上对 Ubuntu WSL 执行了此操作。我不确定您使用的是哪个 OS,这可能会影响行为。