ファイルが変更されたかどうかを検出するためにpyinotifyを使用しようとしています。
そうしてみてください
def status(argument):
global email_alarm_status
global new_email_alarm
if not email_alarm_status:
with open('pathtofile') as fp:
email_alarm_status = fp.read()
with open("pathtofile","w") as cp:
cp.write(email_alarm_status)
with open('pathtofile') as fp:
with open("pathtofile") as cp:
if cp.read() != fp.read():
print "changed"
email_alarm_status = fp.read()
wm = pyinotify.WatchManager()
notifier = pyinotify.Notifier(wm)
wm.add_watch('pathtofile', pyinotify.IN_MODIFY)
notifier.loop(callback=status)
値が変わると「通知」します。これで問題は、notifier.loopがイベントに関する情報を印刷して「オフ」を試み、次のようにstdoutを少し開いてみました。
class NullDevice():
def write(self, s):
pass
original_stdout = sys.stdout # keep a reference to STDOUT
sys.stdout = NullDevice() # redirect the real STDOUT
print "2 - this won't print"
sys.stdout = original_stdout # turn STDOUT back on
print "3 - this will print to SDTDOUT"
wm = pyinotify.WatchManager()
notifier = pyinotify.Notifier(wm)
wm.add_watch('/home/pi/socketserver/var', pyinotify.IN_MODIFY)
sys.stdout = f
notifier.loop(callback=status)
sys.stdout = original_stdout # turn STDOUT back on
print "3 - this will print to SDTDOUT"
しかし、うまくいきません。 pyinotifyからエラーを返します...
pi@TestEnv:~ $ python ./python/handler
Traceback (most recent call last):
File "./python/handler", line 83, in <module>
notifier.loop(callback=status)
File "/usr/local/lib/python2.7/dist-packages/pyinotify.py", line 1390, in loop
self.process_events()
File "/usr/local/lib/python2.7/dist-packages/pyinotify.py", line 1287, in process_events
self._default_proc_fun(revent)
File "/usr/local/lib/python2.7/dist-packages/pyinotify.py", line 924, in __call__
return _ProcessEvent.__call__(self, event)
File "/usr/local/lib/python2.7/dist-packages/pyinotify.py", line 650, in __call__
return self.process_default(event)
File "/usr/local/lib/python2.7/dist-packages/pyinotify.py", line 982, in process_default
self._out.flush()
AttributeError: NullDevice instance has no attribute 'flush'
なぜこれを知っている人がいますか?それとも、ファイルが変更された場合に機能を実装する方法はありますか?
答え1
sys.stdoutをこのように変更することはできません。テキストIOラッパー実際には、ファイル記述子1の実際の標準出力の周りです。その結果、同様のものprint
(またはファイル記述子1に直接書き込まれたもの)は、現在実行中の操作を完全に無視します。真のリダイレクトを達成するには、次のことを行う必要があります。
# Copy standard out to a second file descriptor for restoration
original_stdout = os.dup(sys.stdout.fileno())
# Replace standard out with /dev/null
nullfd = os.open("/dev/null", os.O_WRONLY)
os.dup2(nullfd, sys.stdout.fileno())
os.close(nullfd)
# Do your stuff here
# Restore standard out and close duplicated file descriptor
os.dup2(original_stdout, sys.stdout.fileno())
os.close(original_stdout)
これにより、すべての標準出力が/ dev / nullにリダイレクトされ、完了すると再び復元されます。バラよりos.dupのドキュメント、オペレーティングシステム dup2そしてCで標準ファイル記述子をリダイレクトする方法に関するこのStackOverflowドキュメント(Pythonにも同じ原則が適用されます。)
os
組み込みの機能ではなく、ここで関数を使用する必要があることに注意してくださいopen
。これを行うには、実際のデフォルトのファイル記述子を使用する必要があります。
答え2
アラートを作成するとき:
notifier = pyinotify.Notifier(wm)
イベントを処理するために2番目のパラメータを渡すことができます。デフォルトでは、ハンドラはイベントを印刷します。これを防ぐには、何もしない最小ハンドラを直接作成してください。たとえば、
class NoLog(pyinotify.ProcessEvent):
def process_default(self, event):
pass
handler = NoLog()
notifier = pyinotify.Notifier(wm, default_proc_fun=handler)
バラよりイベント処理