我正在使用 Python 在一次操作中将文本块写入文件:
open(file, 'w').write(text)
如果脚本被中断所以文件写入没有完成我想要没有文件而不是部分完整的文件。这可以做到吗?
原文由 hoju 发布,翻译遵循 CC BY-SA 4.0 许可协议
一个使用 Python 实现原子写入的简单片段 tempfile
。
with open_atomic('test.txt', 'w') as f:
f.write("huzza")
甚至读写同一个文件:
with open('test.txt', 'r') as src:
with open_atomic('test.txt', 'w') as dst:
for line in src:
dst.write(line)
使用两个简单的上下文管理器
import os
import tempfile as tmp
from contextlib import contextmanager
@contextmanager
def tempfile(suffix='', dir=None):
""" Context for temporary file.
Will find a free temporary filename upon entering
and will try to delete the file on leaving, even in case of an exception.
Parameters
----------
suffix : string
optional file suffix
dir : string
optional directory to save temporary file in
"""
tf = tmp.NamedTemporaryFile(delete=False, suffix=suffix, dir=dir)
tf.file.close()
try:
yield tf.name
finally:
try:
os.remove(tf.name)
except OSError as e:
if e.errno == 2:
pass
else:
raise
@contextmanager
def open_atomic(filepath, *args, **kwargs):
""" Open temporary file object that atomically moves to destination upon
exiting.
Allows reading and writing to and from the same filename.
The file will not be moved to destination in case of an exception.
Parameters
----------
filepath : string
the file path to be opened
fsync : bool
whether to force write the file to disk
*args : mixed
Any valid arguments for :code:`open`
**kwargs : mixed
Any valid keyword arguments for :code:`open`
"""
fsync = kwargs.pop('fsync', False)
with tempfile(dir=os.path.dirname(os.path.abspath(filepath))) as tmppath:
with open(tmppath, *args, **kwargs) as file:
try:
yield file
finally:
if fsync:
file.flush()
os.fsync(file.fileno())
os.rename(tmppath, filepath)
原文由 Nils Werner 发布,翻译遵循 CC BY-SA 4.0 许可协议
2 回答5.2k 阅读✓ 已解决
2 回答1.1k 阅读✓ 已解决
4 回答1.4k 阅读✓ 已解决
3 回答1.3k 阅读✓ 已解决
3 回答1.3k 阅读✓ 已解决
2 回答884 阅读✓ 已解决
1 回答1.8k 阅读✓ 已解决
将数据写入临时文件,当数据成功写入后,将文件重命名为正确的目标文件,例如
根据文档 http://docs.python.org/library/os.html#os.replace
笔记:
如果 src 和 dest 位置不在同一个文件系统上,它可能不是原子操作
os.fsync
如果在电源故障、系统崩溃等情况下性能/响应比数据完整性更重要,则可以跳过该步骤