我有两个应用程序(从python编译,仅在Windows上运行)。第一个是预定的:它启动,启动另一个应用程序的几个实例并死掉。此外,此预定应用程序应检查以前启动的子应用程序实例是否仍在运行。
要实现此检查,我尝试使用文件锁定方法:
这在PERL中很容易实现,但我在python中遇到了一些麻烦。
我尝试使用win32 API(从portalocker剪切所需的部分代码)。
以下是测试脚本:
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'
我打开两个Python shell实例并导入这个脚本。 然后我在其中一个中启动go()方法,当它处于休眠状态时,我启动checkFileLock()函数来检查文件是否实际被锁定......而事实并非如此。
我也尝试离开sys.stdin.readline,就像在portalocker中完成一样,在这种情况下文件确实被锁定了。但是没有必要在我的应用程序中听stdin ...
所以我在创建锁的线程中创建了无限循环。在这种情况下,文件也被锁定,但即使在我关闭Python shell之后它也不会被释放,这也是不正确的。
我将非常高兴听到如何解决在Windows中从Python锁定文件的问题。 如果您有任何其他工作方法如何确定该过程是否仍在运行,我也希望听到它。
答案 0 :(得分:2)
我使用代码here来执行此操作。在我的情况下,我总是在Windows中运行,所以我删除了平台检查。它对我有用。
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)
答案 1 :(得分:0)
我对Windows不太熟悉,但Linux中的类似情况使用ps来检查应用程序名称。这假定您具有不同的应用程序名称,并且您正在使用这些名称运行它们。
举个例子,这里检查firefox是否已经在运行。
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'