python 49 lines · 8 steps

Transactional file operations in Python

A FileTransaction records an undo action for every filesystem change so a failure can roll everything back.

Explained by highlit
1import os
2import shutil
3import tempfile
4from contextlib import contextmanager
5 
6 
7class FileTransaction:
8 def __init__(self):
9 self._undo = []
10 
11 def write(self, path, data):
12 existed = os.path.exists(path)
13 backup = None
14 if existed:
15 fd, backup = tempfile.mkstemp()
16 os.close(fd)
17 shutil.copy2(path, backup)
18 mode = "wb" if isinstance(data, (bytes, bytearray)) else "w"
19 with open(path, mode) as f:
20 f.write(data)
21 if existed:
22 self._undo.append(lambda: shutil.move(backup, path))
23 else:
24 self._undo.append(lambda: os.remove(path))
25 
26 def move(self, src, dst):
27 shutil.move(src, dst)
28 self._undo.append(lambda: shutil.move(dst, src))
29 
30 def remove(self, path):
31 fd, backup = tempfile.mkstemp()
32 os.close(fd)
33 shutil.move(path, backup)
34 self._undo.append(lambda: shutil.move(backup, path))
35 
36 def rollback(self):
37 for action in reversed(self._undo):
38 action()
39 self._undo.clear()
40 
41 
42@contextmanager
43def file_transaction():
44 tx = FileTransaction()
45 try:
46 yield tx
47 except Exception:
48 tx.rollback()
49 raise
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Recording an inverse action per operation lets you undo a sequence of side effects atomically.
  2. 2Backing up originals to temp files before overwriting makes writes and deletes reversible.
  3. 3Replaying undo actions in reverse order correctly unwinds dependent changes.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Transactional file operations in Python — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code