1

I want to detect if a file is being written to by another process before I start to read the contents of that file. This is on Windows and I am using Python (2.7.x).

(By the way, the Python script is providing a service where it acts on files that are placed in a specified folder. It acts on the files as soon as they are detected and it deletes the files after having acted on them. So I don't want to start acting on a file that is only partially written.)

I have found empirically that trying to rename the file to the same name will fail if the file is being written to (by another process) and will succeed (as a null-op) if the file is not in use by another process. Something like this:

def isFileInUse(filePath):
    try:
        os.rename(filePath, filePath)
        return False
    except Exception:
        return True

I haven't seen anything documented about the behaviour of os.rename when source and destination are the same. Does anyone know of something that might go wrong with what I am doing above?

I emphasize that I am looking for a solution that works in Windows, and I note that os.access doesn't seem to work - even with os.W_OK it returns True even if the file is being written by another process.

One thing that is nice about the above solution (renaming to the same name) is that it is atomic - which is not true if I try to rename to a temp name, then rename back to the original name.

Cameron Hayne
  • 481
  • 3
  • 4
  • This seems like a backwards way to do it. The program that writes the file should write to a temp name, then rename it to the real name when it's done. – Barmar Apr 29 '16 at 19:46
  • 2
    Trying to detect whether the file is in use as a separate step from opening it is prone to race conditions, because what happens if someone else starts writing right after you perform the check? – user2357112 Apr 29 '16 at 19:46
  • 1
    This might be a helpful topic to your question: http://stackoverflow.com/questions/11114492/check-if-a-file-is-not-open-not-used-by-other-process-in-python – Scratch'N'Purr Apr 29 '16 at 19:47
  • While it would be nice if the program that writes the file writes to a temp file and then renames it when done, I don't have control over that program. My Python script is providing a service to that program (which is to be written by end-users) and I want to make the "API" for that service as simple as possible. – Cameron Hayne Apr 29 '16 at 19:50
  • And in my particular use case, (the service mentioned in previous comment), the "master" program writes files which are to be acted on as soon as they appear in the specified folder. So there is (by definition) no problem of a race condition - if the "master" program starts writing to the file a second time (after having closed it), they have violated the contract and will get what they get. (They will never get a crash since the Python program protects against that.) – Cameron Hayne Apr 29 '16 at 19:54
  • Using the psutil module to loop through all processes, checking if any process has the file open (as suggested in the link provided by Scratch'N'Purr) is a possible solution but I fear that would be slower, and possibly fail due to permissions etc. – Cameron Hayne Apr 29 '16 at 19:57
  • Doesn't Windows have something similar to `lsof`? – jDo Apr 29 '16 at 20:10

1 Answers1

0

Since you only want to read the file - why not just try to do it? Since this is the operation you are trying to do:

try:
    with open("file.txt", "r") as handle:
        content = handle.read()
except IOError as msg:
     pass # error handling

This will try to read the content, and fail if the file is locked, or unreadable.

I see no reason to check if the file is locked if you just want to read from it - just try reading and see if that throws an exception.

tobspr
  • 8,200
  • 5
  • 33
  • 46
  • As I mentioned in a reply to a comment above, my Python script is providing a service where it acts on files that are placed in a specified folder as soon as the files appear there. And it deletes the files after acting on them. So I don't want to start acting on the contents of a file that is only partially written - hence the need to detect when the file is no longer being written to. – Cameron Hayne Apr 29 '16 at 20:04
  • this won't work unless the other process opens file with `dwShareMode==0` which is not true if the other process uses standard CRT functions. Python on Windows happily reads files opened for writing by others. – robyschek Apr 29 '16 at 20:17