0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

python2系で書き込み・読み込みの排他ロック

Last updated at Posted at 2019-09-09

pythonで書き込み読み込み中のファイルにwriteをぶつけるとファイルが壊れる(?)らしく
pythonだけで排他ロックをかけたい場合
fcntl.flock関数を使う

公式リファレンス
https://docs.python.org/ja/3/library/fcntl.html

ロック獲得に失敗した場合に排出されるエラーが、
2系と3系で違うので注意(たしかIOErrorとOSError)。

下記は2系

#!/usr/bin/python
# -*- coding: utf-8 -*-
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 -*-
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))
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?