5

I would like to find via Python script if an application has opened a file. I know there is a lot of proposition out there, but none seems to be doing excactly what I want. I have tried a lot of solutions. But still can't get behavior expected. Want I want is to raise an exception when a python script tries to open a file that is open by pdf reader. For example, if I opened a file with a pdf reader, and try to open/rename it via a Python script, it should raise an exception. I have tried multiple pieces of code:

try:
    myfile = open("myfile.csv", "r+") # or "a+", whatever you need
except IOError:
    print "Could not open file! Please close Excel!"

with myfile:
    do_stuff()

In this question, I tested many scripts and none worked perfectly. When I rename pdf file, even when it is open the rename is accepter and at the end.

This makes me wonder is this is impossible or I am doing wrong.

S3DEV
  • 8,768
  • 3
  • 31
  • 42
dmx
  • 1,862
  • 3
  • 26
  • 48
  • 1
    I don't think there's any general way to do this. Only privileged users can tell what files are open by other users. – Barmar Oct 25 '19 at 20:41

2 Answers2

2

You're right, there aren't many (any?) elegant solutions to this. Here is a cross-platform method I've found to work (in most cases).

Test if the lock file exists.

On Windows:

You won't see this in Win Exploder, but if you run os.listdir() on the file's directory you should see a ~$myfile.xlsx lock file. The naming convention is standard (as far as I know) so you can test for the existence of this file; or better yet, do a regex search.

On Linux:

Similar to the Win solution, look for the lock or swap file, usually named something like ~lock.myfile.xlsx# or .myfile.txt.swp.

Sys Admins: Please feel free to edit this post if you feel appropriate. These are just some simple findings I've stumbled across along the way.

Hope this helps ...

S3DEV
  • 8,768
  • 3
  • 31
  • 42
0

One approach is to call lsof or it's equivalents, depending on the operating system:

import subprocess
import sys

def is_file_open_any_process(path: str) -> bool:
    if sys.platform in ["linux", "darwin"]:
        fnull = open(os.devnull, "w") # to redirect output to devnull
        retcode  = subprocess.call(["lsof", path], stdout=fnull, stderr=subprocess.STDOUT)
        if retcode == 0:
            return True
        return False
    else:
        raise NotImplementedError(f"not implemented for sys.platform: {sys.platform}")