Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

os.link() vs. os.rename() vs. os.replace() for writing atomic write files. What is the best approach?

Tags:

python

Hi am trying to write an atomic write function like so...

with tempfile.NamedTemporaryFile(mode= "w", dir= target_directory) as f: 
     #perform file writing operation  
     os.replace(f.name, target_file_name) 

I am struggling to figure out what would be the best action to do in line 3. Should I use os.replace(), os.rename() or should I create a hard link between tempfile and target file using os.link()?

Does os.link() use more memmory? What are the benefits of each and are all of them atomic?

like image 288
DZtron Avatar asked Feb 24 '20 03:02

DZtron


People also ask

What is OS replace in Python?

replace() method in Python is used to rename the file or directory. If destination is a directory, OSError will be raised. If the destination exists and is a file, it will be replaced without error if the action performing user has permission.

Does OS rename create directory?

rename doesn't create a new directory if the new name is a filename in a directory that does not currently exist. In this case dirname can contain created or not-yet-created subdirectories. As an alternative, one may use os. renames , which handles new and intermediate directories.


1 Answers

os.rename / os.replace are both implemented using this function

The only difference is os.replace uses is_replace=1 which has no effect on posix but sets MOVEFILE_REPLACE_EXISTING flag on windows:

If a file named lpNewFileName exists, the function replaces its contents with the contents of the lpExistingFileName file, provided that security requirements regarding access control lists (ACLs) are met. For more information, see the Remarks section of this topic.

If lpNewFileName or lpExistingFileName name a directory and lpExistingFileName exists, an error is reported.

os.link isn't really suitable for this function unless you can guarantee that the target file does not exist (as os.link will error):

$ touch a b
$ link a b
link: cannot create link 'b' to 'a': File exists
$ python3 -c 'import os; os.link("a", "b")'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
FileExistsError: [Errno 17] File exists: 'a' -> 'b'
like image 173
Anthony Sottile Avatar answered Sep 30 '22 00:09

Anthony Sottile