質問

Possible Duplicate:
Python: single instance of program

I need to prevent a cron job from running concurrent instances when a job takes longer to complete than the launcher interval. I'm trying to use the flock concept to achieve this, but fcntl module is not behaving the way I expect.

Can anyone tell me why this works to prevent two concurrent instances:

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)

And why this does not work:

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
役に立ちましたか?

解決

My humble opinion (although I may be totally wrong) is that file_handle is local to the function (in the second case) and therefore, it gets destroyed once the function is done.

The following code seems to work as expected:

#!/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

Notice that the only thing I did is setting file_handle as global variable (although I copied the whole code to have a working example)

他のヒント

As I mentioned in my commen on @BorrajaX's answer, since it looks like you are POSIX-bound anyway, you could try using a native named semaphore.

You could use the setlock program from D. J. Bernstein's daemontools instead:

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

Easiest way would be to create a file /tmp/scriptlock at the start of the script and check if that file exists before doing work. Make sure the lock file is removed though at the end of processing.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top