我正在尝试使用 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'
有人知道这是为什么吗?或者有什么方法可以实现 if 文件已更改功能?
答案1
你不能像这样修改 sys.stdout ; 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)
您可以传递处理该事件的第二个参数。默认情况下,处理程序打印事件。要阻止这种情况,请创建您自己的不执行任何操作的最小处理程序。例如:
class NoLog(pyinotify.ProcessEvent):
def process_default(self, event):
pass
handler = NoLog()
notifier = pyinotify.Notifier(wm, default_proc_fun=handler)
看处理事件