pythonatomictemporary-filespathlib

Rename temporary file after closing its file descriptor in Python


I want to atomically write files in Python. pathlib and tempfile should be used.

I have

import os
from pathlib import Path
import tempfile


def atomic_write(f: Path, data: bytes) -> None:
    with tempfile.NamedTemporaryFile(dir=f.parent, delete=False) as fp:
        fp.write(data)
        fp.flush()
        os.fsync(fp.fileno())
    Path(fp.name).replace(f)

which works.

Is fp reliably acessible after the with statement or am I getting lucky by accessing it just before it is destroyed?


Solution

  • Yes, the as target clause of a with statement works just like an ordinary assignment as documented, so the target would persist in the namespace until the end of the scope.

    That the target persists after the with statement finishes is useful for inspection of states, as demonstrated in the documentation of urllib.request.urlopen:

    import urllib.request
    DATA = b'some data'
    req = urllib.request.Request(url='http://localhost:8080', data=DATA, method='PUT')
    with urllib.request.urlopen(req) as f:
        pass
    print(f.status)
    print(f.reason)
    

    and for checking an exception captured by the context manager, as shown in the documentation of unittest.TestCase.assertRaises:

    with self.assertRaises(SomeException) as cm:
        do_something()
    
    the_exception = cm.exception
    self.assertEqual(the_exception.error_code, 3)