防止并发运行 Python 脚本实例

8 投票
4 回答
9269 浏览
提问于 2025-04-17 13:15

可能是重复的问题:
Python: 单实例程序

我需要防止一个定时任务在执行时出现多个同时运行的实例,尤其是当这个任务的执行时间超过了启动间隔的时候。我想用“文件锁”的概念来实现这个目的,但发现fcntl模块的表现和我预想的不一样。

有人能告诉我为什么下面的代码可以防止两个实例同时运行吗:

import sys
import time
import fcntl

file_path = '/var/lock/test.py'
file_handle = open(file_path, 'w')

try:
    fcntl.lockf(file_handle, fcntl.LOCK_EX | fcntl.LOCK_NB)
    print 'no other instance is running'
    for i in range(5):
        time.sleep(1)
        print i + 1

except IOError:
    print 'another instance is running exiting now'
    sys.exit(0)

而下面的代码为什么不行呢:

import sys
import time
import fcntl

def file_is_locked(file_path):
    file_handle = open(file_path, 'w')
    try:
        fcntl.lockf(file_handle, fcntl.LOCK_EX | fcntl.LOCK_NB)
        return False
    except IOError:
        return True

file_path = '/var/lock/test.py'

if file_is_locked(file_path):
    print 'another instance is running exiting now'
    sys.exit(0)
else:
    print 'no other instance is running'
    for i in range(5):
        time.sleep(1)
        print i + 1

4 个回答

0

正如我在@BorrajaX的回答下评论的那样,既然你看起来是受限于POSIX标准的,那么你可以试试使用一个本地命名信号量

0

你可以使用D. J. Bernstein的daemontools中的setlock程序来解决这个问题:

http://cr.yp.to/daemontools/setlock.html

8

我个人的看法(虽然我可能错得离谱)是,file_handle 这个变量在函数内部是局部的,也就是说,一旦这个函数执行完,它就会被销毁。

下面的代码看起来是正常工作的:

#!/usr/bin/env python
#http://stackoverflow.com/questions/14406562/prevent-running-concurrent-instances-of-a-python-script

import sys
import time
import fcntl

file_handle = None

def file_is_locked(file_path):
    global file_handle 
    file_handle= open(file_path, 'w')
    try:
        fcntl.lockf(file_handle, fcntl.LOCK_EX | fcntl.LOCK_NB)
        return False
    except IOError:
        return True

file_path = '/var/lock/test.py'

if file_is_locked(file_path):
    print 'another instance is running exiting now'
    sys.exit(0)
else:
    print 'no other instance is running'
    for i in range(5):
        time.sleep(1)
        print i + 1

注意,我做的唯一一件事就是把 file_handle 设置成了全局变量(虽然我复制了整个代码,以便有个可以运行的例子)。

撰写回答