試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

PythonでPyGObjectを用いずにファイルの変更を監視する

Pythonでファイルの変更を監視する (OS非依存・PyGObject使用)」ではGLib(PyGObject/PyGTK)のメインループを用いたタイムアウト機能により定期的に監視処理を実行してファイルの変更を監視したが、ここでは参考としてPyGObjectを用いずにファイルの変更を監視する例を扱う。
(2010/4/12)「GIOライブラリのファイル変更監視機能を用いる」では、PyGObjectのGIOライブラリの言語バインディングを用いてより高度な変更監視を行う方法についてを扱っている。

メモ

全体の流れとしては無限に

  1. ファイルのタイムスタンプをos.path.getmtime()で取得
  2. 前回のタイムスタンプとの比較後、条件によっては更新されたときの処理を実行
  3. time.sleep()で休む*1

を繰り返すというだけで、難しいことはない。しかし、これは端末で実行する必要があり、終了もCtrl+Cなど、UNIXシグナルを用いて止めるしかない。また、プログラムの流れが異なるPyGTKなどのプログラムで使うこともできない。

コマンド行引数に指定したファイルを監視し、更新されると(1秒以内に)メッセージを表示する。Ctrl+Cを押すかタイムスタンプ取得に失敗すると終了する。
Ctrl+Cで止めたときのKeyboardInterruptについてのメッセージが表示されるのが邪魔なら「PythonでUNIXシグナルのハンドラを扱う(後半)」の要領でUNIXシグナルハンドラの設定を行う。
[任意]ファイル名: filewatchtest_nopygobject.py

#! /usr/bin/python
# -*- encoding: utf-8 -*-

import time
import sys
import os

if len(sys.argv) != 2:
  print 'USAGE: %s [FILE]' % sys.argv[0]
  sys.exit(0)

infile = sys.argv[1]
try:
  mtime = os.path.getmtime(infile)
except OSError, (errno, msg):
  print >> sys.stderr, 'Error: cannot stat "%s": %s' % (infile, str(msg))
  sys.exit(1)

print 'start watching "%s" (%s)' % (infile, time.ctime(None))
while True:
  try:
    mtime_new = os.path.getmtime(infile)
  except OSError, (errno, msg):
    print >> sys.stderr, 'Error: cannot stat "%s": %s' % (infile, str(msg))
    sys.exit(1)
  # 新しく取得したタイムスタンプが以前記憶したものと異なれば更新されている
  if mtime_new != mtime:
    mtime = mtime_new  # 新しいものを記憶
    # 更新されたときに行う処理をここに記述
    print 'file "%s" has been updated (%s)' % (infile, time.ctime(mtime))
  time.sleep(1)

関連記事:

使用したバージョン:

*1:この長さが監視の細かさ/変更時の反応の良さに関係してくるが、今回は1秒間隔とした