Python: module for creating PID-based lockfile? Python: module for creating PID-based lockfile? python python

Python: module for creating PID-based lockfile?


This might be of help to you: lockfile


If you can use GPLv2, Mercurial has a module for that:

http://bitbucket.org/mirror/mercurial/src/tip/mercurial/lock.py

Example usage:

from mercurial import error, locktry:    l = lock.lock("/path/to/lock", timeout=600) # wait at most 10 minutes    # do somethingexcept error.LockHeld:     # couldn't take the lockelse:    l.release()


i've been pretty unhappy with all of those, so i wrote this:

class Pidfile():    def __init__(self, path, log=sys.stdout.write, warn=sys.stderr.write):        self.pidfile = path        self.log = log        self.warn = warn    def __enter__(self):        try:            self.pidfd = os.open(self.pidfile, os.O_CREAT|os.O_WRONLY|os.O_EXCL)            self.log('locked pidfile %s' % self.pidfile)        except OSError as e:            if e.errno == errno.EEXIST:                pid = self._check()                if pid:                    self.pidfd = None                    raise ProcessRunningException('process already running in %s as pid %s' % (self.pidfile, pid));                else:                    os.remove(self.pidfile)                    self.warn('removed staled lockfile %s' % (self.pidfile))                    self.pidfd = os.open(self.pidfile, os.O_CREAT|os.O_WRONLY|os.O_EXCL)            else:                raise        os.write(self.pidfd, str(os.getpid()))        os.close(self.pidfd)        return self    def __exit__(self, t, e, tb):        # return false to raise, true to pass        if t is None:            # normal condition, no exception            self._remove()            return True        elif t is PidfileProcessRunningException:            # do not remove the other process lockfile            return False        else:            # other exception            if self.pidfd:                # this was our lockfile, removing                self._remove()            return False    def _remove(self):        self.log('removed pidfile %s' % self.pidfile)        os.remove(self.pidfile)    def _check(self):        """check if a process is still runningthe process id is expected to be in pidfile, which should exist.if it is still running, returns the pid, if not, return False."""        with open(self.pidfile, 'r') as f:            try:                pidstr = f.read()                pid = int(pidstr)            except ValueError:                # not an integer                self.log("not an integer: %s" % pidstr)                return False            try:                os.kill(pid, 0)            except OSError:                self.log("can't deliver signal to %s" % pid)                return False            else:                return pidclass ProcessRunningException(BaseException):    pass

to be used something like this:

try:    with Pidfile(args.pidfile):        process(args)except ProcessRunningException:    print "the pid file is in use, oops."