45

I'm working on a python script that will be accessed via the web, so there will be multiple users trying to append to the same file at the same time. My worry is that this might cause a race condition where if multiple users wrote to the same file at the same time and it just might corrupt the file.

For example:

#!/usr/bin/env python g = open("/somepath/somefile.txt", "a") new_entry = "foobar" g.write(new_entry) g.close 

Will I have to use a lockfile for this as this operation looks risky.

3
  • 1
    Maybe you can just use syslog? Commented Aug 7, 2012 at 20:25
  • If you are on Linux or other Unix mkfifo may be an interesting option. mkfifo creates a FIFO special file. Anyone can write to the file at random, then one single process reads out of the FIFO. That way you don't need to use file locking. Commented Aug 7, 2012 at 20:43
  • If you open with O_APPEND, the target filesystem is POSIX-compliant, and your writes are all short enough to be accomplished in a single syscall, there will be no corruption in the first place. Commented Mar 5, 2020 at 13:32

4 Answers 4

58

You can use file locking:

import fcntl new_entry = "foobar" with open("/somepath/somefile.txt", "a") as g: fcntl.flock(g, fcntl.LOCK_EX) g.write(new_entry) fcntl.flock(g, fcntl.LOCK_UN) 

Note that on some systems, locking is not needed if you're only writing small buffers, because appends on these systems are atomic.

Sign up to request clarification or add additional context in comments.

13 Comments

Nice answer, why would you need to do a g.seek(0,2) here to go to EOF. Won't append just add to the end of the file?
What would happen if a user tried to append to the file but the file was locked by flock? Error?
@RayY No, the process (or more precisely, the current thread) just blocks until the lock is released. For more information, refer to man 2 flock
@Flint No, blocked means that flock will not return until it has acquired a lock.
Thank you very much for your help! I could not use buffering=0 since I was not opening the file in binary mode, but using flush on the file descriptor before releasing the lock resolved the issue.
|
7

If you are doing this operation on Linux, and the cache size is smaller than 4KB, the write operation is atomic and you should be good.

More to read here: Is file append atomic in UNIX?

Comments

6

You didn't state what platform you use, but here is an module you can use that is cross platform: File locking in Python

2 Comments

This link is dead.
No it's not, it's just resting.
1

Depending on your platform/filesystem location this may not be doable in a safe manner (e.g. NFS). Perhaps you can write to different files and merge the results afterwards?

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.