Question

I have two applications (compiled from python, running on Windows only). The first one is scheduled: it starts, launches several instances of another application and dies. Also, this scheduled app should check if previously started instances of child app are still running.

To implement this check I tried to use files lock method:

  1. Create file in child app and get explicit lock on it. In case if app crashes the lock should be released automatically.
  2. Check this file from scheduled app. If it is locked - that means that child app is still running.

This is very easy to implement in PERL, but I've met some troubles in python.

I tried to use win32 API (cut required part of code from portalocker).

Here is the test script:

import os
import win32con
import win32file
import pywintypes
import sys
import time
import threading

def createLockFile(filePath = "c:\\\\test.tmp"):
    file = open(filePath, "a+")
    hfile = win32file._get_osfhandle(file.fileno())
    win32file.LockFileEx(hfile, win32con.LOCKFILE_EXCLUSIVE_LOCK, 0, -0x10000, pywintypes.OVERLAPPED())

def lockFile(filePath = "c:\\\\test.tmp"):
    t = threading.Thread(target=createLockFile, args=(filePath,))
    t.start()

def checkFileLock(filePath = "c:\\\\test.tmp"):
    log = open(filePath, "a+")
    #here should be IOError: [Errno 13] in case of error
    print 'File is not locked'

def go():
    print 'start'
    lockFile()
    print 'file locked'
    print 'sleeping'
    time.sleep(30)
    print 'getting up'

I open two instances of Python shell and import this script. Then I launch go() method in one of it and while it is sleeping I launch checkFileLock() function to check if file is actually locked... And it is not.

I also tried to leave sys.stdin.readline like it is done in portalocker and in this case the file is really locked. But there is no need to listen to stdin in my app...

So I've created infinite loop in the thread which creates the lock. In this case the file is also locked but it is not released even after I close the Python shell which also is not correct.

I will be very please to hear how to solve the problems with locking files from Python in Windows. If you have any other working methods of how to definitely know if the process is still running I would like to hear it also.

Was it helpful?

Solution

I use the code here to do it. In my case, I'm always running in Windows, so I removed the platform checks. It's worked well for me.

import os, time, sys

class SingleInstance:
    def __init__(self, filename):
        self.lockfile = filename

        try:
            # file already exists, we try to remove (in case previous execution was interrupted)
            if os.path.exists(self.lockfile):
                os.unlink(self.lockfile)

            self.fd =  os.open(self.lockfile, os.O_CREAT|os.O_EXCL|os.O_RDWR)

        except OSError as e:
            if e.errno == 13:
                print("Another instance is already running, quitting.")
                #sys.exit(-1)

            print(e.errno)
            raise

        except Exception as x:
            print(x)

    def __del__(self):
        import sys

        if hasattr(self, 'fd'):
            os.close(self.fd)
            os.unlink(self.lockfile)

OTHER TIPS

I am not familiar enough with Windows, but a similar situation in Linux uses the ps to check on the application name. This assumes that you have different names for the applications and you are running them with those names.

As an example, here is a check if firefox is already running.

psout = subprocess.Popen(['ps', 'ax'], stdout=subprocess.PIPE).communicate()[0]
if 'firefox' not in psout:
  print 'Firefox has not yet been started'
  subprocess.Popen(['firefox', '-new-tab'])
else:
  print 'Firefox already running'
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top