import os
import sys
import atexit
class ProcessRunning(Exception):
pass
def removePidFile(pidfile):
pidfile.remove()
class PidFile:
def __init__(self, path):
self._path = path
self._createdPID = 0
if os.path.exists(path):
try:
pid = int(open(path).read())
except (IOError, ValueError, TypeError):
# can't open file or read PID from file. File is probably
# invalid or stale, so try to delete it.
pid = None
print "%s is invalid or cannot be opened; " \
"attempting to remove it." % path
os.unlink(path) # should we catch errors here?
else:
if self.pidRunning(pid):
raise ProcessRunning()
else:
print "%s is stale; removing." % path
try:
os.unlink(path)
except OSError:
# maybe the other process has just quit
# and has removed the file.
pass # try continuing...
pidfile = open(path, 'w')
pidfile.write(str(self.currentPID()))
pidfile.close()
self._createdPID = 1
# Delete the pid file when python exits, so that the pid file is
# removed if the process exits abnormally.
# If the process crashes, though, the pid file will be left behind.
atexit.register(removePidFile, self)
def pidRunning(self, pid):
if os.name == 'posix':
try:
os.kill(pid, 0)
except OSError, e:
if e.errno == 3: # No such process
return 0
return 1
else:
try:
import win32api
import win32con
import pywintypes
try:
win32api.OpenProcess(
win32con.PROCESS_QUERY_INFORMATION, 0, pid)
except pywintypes.error, e:
if e[0] == 87: # returned when process does not exist
return 0
except ImportError:
pass # couldn't import win32 modules
return 1
def currentPID(self):
if os.name == 'posix':
return os.getpid()
else:
try:
import win32api
except ImportError:
pass
if sys.modules.has_key('win32api'):
return win32api.GetCurrentProcessId()
return None
def __del__(self):
self.remove()
def remove(self):
# Only remove the file if we created it. Otherwise attempting to start
# a second process will remove the file created by the first.
if self._createdPID:
try:
os.unlink(self._path)
except (AttributeError, OSError):
pass
|