Python|ファイルロックによる排他制御

1. はじめに

複数のプロセスやスレッドが同じファイルに同時にアクセスすると、データの競合や破損が発生することがあります。こうした問題を防ぐために重要なのが「ファイルロックによる排他制御」です。
本記事では、Pythonでファイルロックを実現する方法について、初心者にもわかりやすく解説します。具体的には、fcntlモジュール(Linux/Unix向け)とmsvcrtモジュール(Windows向け)を使った方法を紹介します。

排他制御はログファイルの書き込み、バッチ処理の同時実行防止、設定ファイルの一貫性保持など、実務でもよく使われます。コード例と実行結果を通じて、理解を深めていきましょう。

 

2. Pythonでファイルロックによる排他制御を行う基本

2-1. ファイルロックとは?

ファイルロックとは、あるプロセスがファイルを使用中に、他のプロセスがそのファイルへアクセスするのを制限する仕組みです。排他制御とも呼ばれます。これにより、同時書き込みや読み書きによる競合を防止できます。

2-2. Linux/Unix環境でのファイルロック(fcntl)

LinuxやmacOSなどのUnix系OSでは、fcntlモジュールを使用します。

import fcntl
import time

# ファイルを開く
with open("lockfile.txt", "w") as f:
    print("ファイルをロック中...")
    # 排他ロック(書き込み排他)
    fcntl.flock(f, fcntl.LOCK_EX)
    f.write("このファイルはロックされています。\n")
    time.sleep(5)  # 処理中(別プロセスでの同時アクセスを試すならこの間に)
    # ロック解除
    fcntl.flock(f, fcntl.LOCK_UN)
    print("ロックを解除しました。")

実行結果:

ファイルをロック中...
ロックを解除しました。

2-3. Windows環境でのファイルロック(msvcrt)

Windowsではmsvcrtモジュールを使用します。

import msvcrt
import time

with open("lockfile.txt", "w") as f:
    print("ファイルをロック中...")
    msvcrt.locking(f.fileno(), msvcrt.LK_NBLCK, 1024)
    f.write("このファイルはロックされています。\n")
    time.sleep(5)
    msvcrt.locking(f.fileno(), msvcrt.LK_UNLCK, 1024)
    print("ロックを解除しました。")

実行結果:

ファイルをロック中...
ロックを解除しました。

 

3. よくある使い方・応用例

3-1. 複数プロセスでの同時実行防止

例えば、定期的に実行されるバッチ処理やログ記録プログラムなどで、2つのプロセスが同時にファイルを書き換えないように制御する用途があります。

3-2. with構文と関数で再利用性のあるロック処理

ロック処理を関数化することで、複数の場所で再利用しやすくなります。

import fcntl
import time

def write_with_lock(filename, text):
    with open(filename, "a") as f:
        fcntl.flock(f, fcntl.LOCK_EX)
        f.write(text + "\n")
        time.sleep(1)
        fcntl.flock(f, fcntl.LOCK_UN)

# 呼び出し例
write_with_lock("log.txt", "ログ出力1")
write_with_lock("log.txt", "ログ出力2")

実行結果:

(log.txtに以下が追記される)
ログ出力1
ログ出力2

3-3. try-exceptを使った安全なロック処理

エラーが発生してもロックが解除されるように、try-except-finally構文を活用します。

import fcntl

try:
    f = open("data.txt", "a")
    fcntl.flock(f, fcntl.LOCK_EX)
    f.write("排他制御中に書き込みました。\n")
except Exception as e:
    print(f"エラーが発生しました: {e}")
finally:
    fcntl.flock(f, fcntl.LOCK_UN)
    f.close()

実行結果:

(正常時はエラーなし、ファイルに追記)

 

4. 注意点・エラー対策

4-1. ロックできるのは「同一ファイルハンドル」だけ

Pythonのロックはあくまでプロセス間での協調動作に依存しているため、すべてのプログラムがロックを守るとは限りません。

4-2. WindowsとUnixでモジュールが異なる

PythonのfcntlモジュールはUnix系でのみ使用可能、msvcrtはWindows専用です。OSによって使い分けが必要です。

4-3. ロック解除を忘れない

ロックしたまま異常終了すると、ファイルがずっと使えなくなる恐れがあります。with構文やfinallyブロックを使って確実にロックを解除しましょう。

 

5. まとめ

  • Pythonではfcntl(Unix)やmsvcrt(Windows)を使ってファイルロックが可能
  • 排他制御により、データ競合や破損を防げる
  • with構文やtry-finallyでロック解除を忘れずに

ファイルロックは、ログ出力、バッチ処理、設定ファイル編集など、実務で非常に役立つテクニックです。まずはシンプルなサンプルコードから試してみて、徐々に応用パターンに取り組んでみましょう。

タイトルとURLをコピーしました