파일이 변경되었는지 감지하기 위해 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)
이벤트를 처리하기 위해 두 번째 매개변수를 전달할 수 있습니다. 기본적으로 핸들러는 이벤트를 인쇄합니다. 이를 방지하려면 아무 작업도 수행하지 않는 최소 핸들러를 직접 만드세요. 예를 들어:
class NoLog(pyinotify.ProcessEvent):
def process_default(self, event):
pass
handler = NoLog()
notifier = pyinotify.Notifier(wm, default_proc_fun=handler)
바라보다이벤트 처리