Tag Archives: python

Harness the Python “With” Statement

Arg. I love the python “with” statement, but I can never remember the signatures of the methods to support it. So here it is:

class with_class():
    def __enter__(self):
        return self  # or something else

    def __exit__(self, type, value, traceback):
        pass

with with_class() as thing:
    pass

Taken from this awesome page, which explains it really well:

http://effbot.org/zone/python-with-statement.htm

Leave a comment

Filed under python, Uncategorized

Python Lockfile using With

I needed lockfile functionality and wanted to use the Python with statement. It creates a lockfile, or else blows away an existing lockfile that’s been there too long.

import os, sys
import fcntl
import errno
import time
from contextlib import contextmanager


@contextmanager
def file_lock(lock_file, timeout=15 * 60):

    # assume no
    fp = None

    try:
        # create the file or fail
        fp = _create(lock_file)
        yield True
    except OSError as e:
        if e.errno != errno.EEXIST:
            raise

        # TODO: check the modified time to see if we should go anyway
        try:
            fp = _refresh(lock_file, timeout)
        except:
            fp = None

        if fp:
            yield True
        else:
            yield False

    finally:
        # clean up after
        if fp:
            _cleanup(fp, lock_file)


def _create(lock_file):
    """Create the file or fail."""
    fp = os.open(lock_file, os.O_CREAT | os.O_EXCL | os.O_RDWR)
    return fp


def _refresh(lock_file, timeout):
    """too old, just overwrite it to update the modified time"""
    fp = os.open(lock_file, os.O_RDWR)
    mtime = time.time() - os.fstat(fp).st_mtime
    if mtime < timeout:
        fp = None
    else:
        fcntl.lockf(fp, fcntl.LOCK_EX | fcntl.LOCK_NB)
        os.write(fp, 'ok')
    return fp


def _cleanup(fp, lock_file):
    """unlock and delete the file"""
    os.close(fp)
    os.unlink(lock_file)

if __name__ == '__main__':
    pass

    with file_lock('zoom.lock') as got_it:
        if got_it:
            print 'Got it!'
            time.sleep(10)
        else:
            print 'EPIC FAIL'

        print 'done'

Leave a comment

Filed under python, utility