2

I am doing scientific programming in python, which requires me to run the same script in parallel with minor parameter tweaks. Also I frequently exit the program with either a keyboard interrupt or an exception being raised.

I'd like to use locks to prevent writing into a directory I may already be working in with another instance of my script. I tried lockfile, and in cases of interrupts/exceptions the lock remains on the directory. Is there any way I could release locks when my program is exiting, both "legally" and due to exceptions/interrupts. I am thinking can I somehow work with the garbage collection routines and add in the provision to unlock the directory?

quamrana
  • 37,849
  • 12
  • 53
  • 71
user3246971
  • 233
  • 2
  • 6

3 Answers3

1

To unlock file in case of exception you can use finally statement which is executed in both cases: if try statement succeeds and also if exception is raised.
More Info: https://docs.python.org/2/tutorial/errors.html#defining-clean-up-actions

To unlock when you hit keyboard interrupt you will have to implement custom handling of this signal. In the handling method you will release lock and then exit program.
Writing custom signal handler is well described here: How do I capture SIGINT in Python?

Community
  • 1
  • 1
  • I was trying to stay away from placing the entire code inside a try except block. I was thinking about importing a module which makes the lock instance, and have this instance be the last to be destroyed. in its destructor ill put the unlock. if i have understood quamrana correctly that is – user3246971 Apr 09 '15 at 05:37
0

I tried this with Python 3.3

# Print something when program exits

class FinalExit:
    def __del__(self):
        print('FinalExit')


class AnException(Exception):
    pass


def throwException():
    raise AnException()


if __name__ == '__main__':
    f=FinalExit()
    throwException()
    print('Not Printed')

The output is:

Traceback (most recent call last):
  File "GC.py", line 20, in <module>
    throwException()
  File "GC.py", line 13, in throwException
    raise AnException()
__main__.AnException
FinalExit

Note the text FinalExit occurs after the detail about the exception, but the text Not Printed is indeed not printed.

I'm sure you can use this principle to create and destroy a lock file.

quamrana
  • 37,849
  • 12
  • 53
  • 71
  • ah so you mean that i just put the unlock within the destructor of an instance, and have that instance be the last to be destroyed? – user3246971 Apr 09 '15 at 05:34
  • This is probably nit picking but you cannot safely assume that __del__() is always called. In addition (according to documentation https://docs.python.org/2/reference/datamodel.html#object.__del__ ) there is good possibility that if __del__() is called as result of program being done with execution, __del__() of your method may be called after destruction of other imported object. This can cause that your calls for release of lock wont be executed because modules responsible for release function were already destroyed – Martin Kalcok Apr 09 '15 at 11:49
0

You can use lockfile-create if you are on linux:

import os
import sys
from time import sleep

from subprocess import check_call, CalledProcessError

try:
    check_call(["lockfile-create", "-q","-p", "-r", "0", "-l", "my.lock"])
except CalledProcessError as e:
    print("{} is already running".format(sys.argv[0]))
    print(e.returncode)
    exit(1)


# main body

for i in range(10):
    sleep(2)
    print(1)

check_call(["rm","-f","my.lock"])

Using the -p flag means the pid of the process will be written to the lock file, the pid is used to see if the process is still active or if the lock file is stale.

See this answer for a full explanation.

Community
  • 1
  • 1
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321