15

My goal is to know if a file is locked by another process or not, even if I don't have access to that file!

So to be more clear, let's say I'm opening the file using python's built-in open() with 'wb' switch (for writing). open() will throw IOError with errno 13 (EACCES) if:

  1. the user does not have permission to the file or
  2. the file is locked by another process

How can I detect case (2) here?

(My target platform is Windows)

feetwet
  • 3,248
  • 7
  • 46
  • 84
Ali
  • 1,503
  • 2
  • 15
  • 20
  • 2
    check http://stackoverflow.com/questions/1861836/checking-file-permissions-in-linux-with-python – monkut Nov 14 '12 at 00:57
  • 1
    Once you've determined the user has permissions and you still get the exception then you know case (2) has been hit. – monkut Nov 14 '12 at 00:58
  • Do you know how the other process is locking the file? It seems like there are [multiple ways](http://en.wikipedia.org/wiki/File_locking#In_Unix-like_systems) to do it. – Sam Mussmann Nov 14 '12 at 01:00
  • Suppose you get an answer to this question; what do you propose to do with the information? – Karl Knechtel Nov 14 '12 at 01:17
  • 1
    @KarlKnechtel report the proper response to the user. – Ali Nov 14 '12 at 01:27

3 Answers3

7

You can use os.access for checking your access permission. If access permissions are good, then it has to be the second case.

Harman
  • 1,571
  • 1
  • 19
  • 31
  • 1
    os.access seems to be the way to go, however, on windows, os.access("myfile", os.R_OK) is returning True for a file that I don't have permission to. – Ali Nov 14 '12 at 01:30
  • 2
    @Ali - you are right. os.access does not return correct value in windows. here is the issue at python.org [http://bugs.python.org/issue2528]. It also provides a patch, but I am not sure if it is trivial to apply the patch. – Harman Nov 14 '12 at 06:58
  • 2
    thank you for pointing out the bug. Apparantly using win32security, it is easy to get ACL permissions on a file in windows. – Ali Nov 14 '12 at 17:44
  • 4
    Ten years later, the python [issue](https://bugs.python.org/issue2528) is still open... – djvg Mar 31 '22 at 09:56
6

As suggested in earlier comments, os.access does not return the correct result.

But I found another code online that does work. The trick is that it attempts to rename the file.

From: https://blogs.blumetech.com/blumetechs-tech-blog/2011/05/python-file-locking-in-windows.html

def isFileLocked(filePath):
    '''
    Checks to see if a file is locked. Performs three checks
        1. Checks if the file even exists
        2. Attempts to open the file for reading. This will determine if the file has a write lock.
            Write locks occur when the file is being edited or copied to, e.g. a file copy destination
        3. Attempts to rename the file. If this fails the file is open by some other process for reading. The 
            file can be read, but not written to or deleted.
    @param filePath:
    '''
    if not (os.path.exists(filePath)):
        return False
    try:
        f = open(filePath, 'r')
        f.close()
    except IOError:
        return True

    lockFile = filePath + ".lckchk"
    if (os.path.exists(lockFile)):
        os.remove(lockFile)
    try:
        os.rename(filePath, lockFile)
        sleep(1)
        os.rename(lockFile, filePath)
        return False
    except WindowsError:
        return True
paolov
  • 2,139
  • 1
  • 34
  • 43
  • It is interesting solution but sleep for one second is too long for most tasks – Olejan Nov 17 '20 at 15:19
  • This is the first attempt here that works for me (kind of). In my case I want to access an excel file. Opening it with read mode doesn't help. Write mode creates a new empty thus broken file. Appending mode works! In addition the probably more elegant way is searching for a lockfile. Here you are right: In case of Excel in Windows there is a hidden file named `~$excelfilename.xlsx` . – Meredith Hesketh Fortescue Apr 28 '21 at 15:05
3

According to the docs:

errno.EACCES
    Permission denied
errno.EBUSY

    Device or resource busy

So just do this:

try:
    fp = open("file")
except IOError as e:
    print e.errno
    print e

Figure out the errno code from there, and you're set.

twasbrillig
  • 17,084
  • 9
  • 43
  • 67
PearsonArtPhoto
  • 38,970
  • 17
  • 111
  • 142