Skip to content

Instantly share code, notes, and snippets.

@dequn
Created December 17, 2017 02:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dequn/e8e55a408340535d543230a0c5c5ea6a to your computer and use it in GitHub Desktop.
Save dequn/e8e55a408340535d543230a0c5c5ea6a to your computer and use it in GitHub Desktop.
A custom-file-lock wrapper for fcntl in python
#coding: utf-8
import os
import time
import fcntl
import contextlib
import logging
@contextlib.contextmanager
def open_file(filename, pattern = 'r', timeout = 5):
""" 以加锁的方式读取文件,尝试timeout * 10 次,每次sleep 1秒钟.
Keyword arguments:
filename -- file to open
pattern: 文件打开方式,'r' or 'w'
timeout: try times (default 5)
"""
fd = open(filename, pattern)
if pattern == 'r' or pattern == 'rb':
lock_type = fcntl.LOCK_SH
elif pattern == 'w' or pattern == 'wb':
lock_type = fcntl.LOCK_EX
else:
raise Exception('Wrong pattern!')
# try to acquire the lock
get_lock = False
try:
for i in xrange(int(timeout * 10)):
fcntl.flock(fd, lock_type | fcntl.LOCK_NB)
get_lock = True
logging.debug('Acquire lock of file %s success!' % filename)
break
except IOError:
time.sleep(1)
if not get_lock:
# close file
fd.close()
raise IOError('Unable to acquire lock for %s' % filename)
yield fd
# unlock
fcntl.flock(fd, fcntl.LOCK_UN)
logging.debug('Release lock of file %s success!' % filename)
# close file
fd.close()
if __name__ == '__main__':
with open_file('./test', 'r') as fin:
for line in fin:
print line
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment