python2系で排他ロックする方法
pythonで書き込み・読み込み中のファイルにwriteをぶつけるとファイルが壊れる(?)らしい。 DBとか使えば勝手に排他かけてくれるらしいけど、まあpythonだけでやるならどうしましょって話。
・解 fcntl.flock関数を使う
・参考 公式リファレンス fcntl --- fcntl および ioctl システムコール — Python 3.7.4 ドキュメント
・注意点 ロック獲得に失敗した場合に排出されるエラーが、 2系と3系で違うので注意(IOErrorとOSError)。
下記は2系
#!/usr/bin/python # -*- coding: utf-8 -*- #読み込み("r")の共有ロックスクリプト import fcntl import inspect import time max_retry_count = 3 pouse_second = 1 try: with open("/home/foo/bat.txt", 'r') as fileobj: for i in range(max_retry_count): try: # ロック獲得(共有ロック) fcntl.flock(fileobj.fileno(), fcntl.LOCK_SH | fcntl.LOCK_NB) except IOError as ioerror: "/home/foo/record.log".write('{n}:{f}:{m}'.format( n=__name__, f=inspect.currentframe().f_code.co_name, m=ioerror.args)) if i + 1 == max_retry_count: raise # ロック獲得失敗 time.sleep(pouse_second) continue try: # ロック獲得成功 wifi_ap_id = fileobj.read() break except Exception as e: # 異常発生 raise ValueError(e) finally: fcntl.flock(fileobj.fileno(), fcntl.LOCK_UN) except Exception as e: "/home/foo/record.log".write('{n}:{f}:{m}'.format( n=__name__, f=inspect.currentframe().f_code.co_name, m=e.args))
#!/usr/bin/python # -*- coding: utf-8 -*- #書き込み("w")の専有ロックスクリプト import fcntl import inspect import time max_retry_count = 3 pouse_second = 1 try: filepath = "/home/foo.kakikomisaki.txt" jstr = "kakikomitaimoji" if os.path.isfile(filepath): option = "r+" else: option = "w" with open(filepath, option) as fileobj: for i in range(max_retry_count): try: # ロック獲得 fcntl.flock(fileobj.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB) except IOError as ioerror: "/home/foo/record.log".write('{n}:{f}:{m}'.format( n=__name__, f=inspect.currentframe().f_code.co_name, m=ioerror.args)) if i + 1 == max_retry_count: raise # ロック獲得失敗 time.sleep(pouse_second) continue try: # ロック獲得成功 ボディ部保存 fileobj.truncate() fileobj.write(jstr) break except Exception as e: # 異常発生 raise ValueError(e) finally: fcntl.flock(fileobj.fileno(), fcntl.LOCK_UN) except Exception as _exception: "/home/foo/record.log".write('{n}:{f}:{m}'.format( n=__name__, f=inspect.currentframe().f_code.co_name, m=_exception.args))
差分もまるまる書いちゃった\(^o^)/ コピペでスクリプトとして動かせる~わーい