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