0

我有两个应用程序(从 python 编译,仅在 Windows 上运行)。第一个是计划好的:它启动,启动另一个应用程序的几个实例,然后死掉。此外,此计划应用程序应检查以前启动的子应用程序实例是否仍在运行。

为了实现这个检查,我尝试使用文件锁定方法:

  1. 在子应用程序中创建文件并对其进行显式锁定。如果应用程序崩溃,锁应自动释放。
  2. 从计划的应用程序检查此文件。如果它被锁定 - 这意味着子应用程序仍在运行。

这在 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 中完成的那样,在这种情况下,文件确实被锁定了。但是没有必要在我的应用程序中收听标准输入......

所以我在创建锁的线程中创建了无限循环。在这种情况下,文件也被锁定,但即使在我关闭 Python shell 后它也不会被释放,这也是不正确的。

我将很高兴听到如何解决在 Windows 中从 Python 锁定文件的问题。如果您有任何其他工作方法可以确定该进程是否仍在运行,我也想听听。

4

2 回答 2

2

我使用这里的代码来做到这一点。就我而言,我总是在 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)
于 2014-02-24T16:50:55.870 回答
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'
于 2014-02-24T16:33:27.397 回答