[python] 파일이 변경되었는지 어떻게 확인합니까?

변경 사항을보고 싶은 다른 프로세스에서 로그 파일을 작성하고 있습니다. 변경이 발생할 때마다 처리를 위해 새 데이터를 읽고 싶습니다.

가장 좋은 방법은 무엇입니까? PyWin32 라이브러리에서 일종의 후크가 있기를 바랐습니다. win32file.FindNextChangeNotification함수를 찾았 지만 특정 파일을 보도록 요청하는 방법을 모릅니다.

누군가 이와 같은 일을한다면 정말 어떻게 들었는지 감사하게 생각합니다.

[편집] 필자는 폴링이 필요없는 솔루션을 따르고 있다고 언급 했어야합니다.

[편집] 저주! 매핑 된 네트워크 드라이브에서는 작동하지 않는 것 같습니다. Windows가 로컬 디스크에서와 같은 방식으로 파일에 대한 업데이트를 듣지 않는다고 생각합니다.



답변

http://timgolden.me.uk/python/win32_how_do_i/watch_directory_for_changes.html 에있는 설명서를 이미 보셨습니까 ? Windows에서만 작동 해야하는 경우 두 번째 예는 정확히 원하는 것 같습니다 (보고 싶은 파일 중 하나와 디렉토리 경로를 교환하는 경우).

그렇지 않으면, 폴링은 아마도 플랫폼에 독립적 인 유일한 옵션 일 것입니다.

참고 : 나는 이러한 해결책을 시도하지 않았습니다.


답변

워치 독 을 사용해 보셨습니까 ?

파일 시스템 이벤트를 모니터링하는 Python API 라이브러리 및 셸 유틸리티

간편한 디렉토리 모니터링

  • 크로스 플랫폼 API.
  • 디렉토리 변경에 대한 응답으로 명령을 실행하는 쉘 도구입니다.

빠른 시작 의 간단한 예제로 빠르게 시작하십시오


답변

폴링이 충분하다면 “수정 된 시간”파일 통계가 변경되는지 확인합니다. 그것을 읽으려면 :

os.stat(filename).st_mtime

또한 Windows 기본 변경 이벤트 솔루션은 네트워크 드라이브와 같은 모든 상황에서 작동하지 않습니다.

import os

class Monkey(object):
    def __init__(self):
        self._cached_stamp = 0
        self.filename = '/path/to/file'

    def ook(self):
        stamp = os.stat(self.filename).st_mtime
        if stamp != self._cached_stamp:
            self._cached_stamp = stamp
            # File has changed, so do something...


답변

멀티 플랫폼 솔루션을 원하면 QFileSystemWatcher 를 확인 하십시오 . 다음은 예제 코드입니다 (위생되지 않음).

from PyQt4 import QtCore

@QtCore.pyqtSlot(str)
def directory_changed(path):
    print('Directory Changed!!!')

@QtCore.pyqtSlot(str)
def file_changed(path):
    print('File Changed!!!')

fs_watcher = QtCore.QFileSystemWatcher(['/path/to/files_1', '/path/to/files_2', '/path/to/files_3'])

fs_watcher.connect(fs_watcher, QtCore.SIGNAL('directoryChanged(QString)'), directory_changed)
fs_watcher.connect(fs_watcher, QtCore.SIGNAL('fileChanged(QString)'), file_changed)


답변

Windows에서는 작동하지 않지만 (cygwin? 일 수 있음) UNIX 사용자의 경우 “fcntl”시스템 호출을 사용해야합니다. 다음은 Python의 예입니다. C로 작성 해야하는 경우 대부분 동일한 코드입니다 (동일한 함수 이름)

import time
import fcntl
import os
import signal

FNAME = "/HOME/TOTO/FILETOWATCH"

def handler(signum, frame):
    print "File %s modified" % (FNAME,)

signal.signal(signal.SIGIO, handler)
fd = os.open(FNAME,  os.O_RDONLY)
fcntl.fcntl(fd, fcntl.F_SETSIG, 0)
fcntl.fcntl(fd, fcntl.F_NOTIFY,
            fcntl.DN_MODIFY | fcntl.DN_CREATE | fcntl.DN_MULTISHOT)

while True:
    time.sleep(10000)


답변

pyinotify를 확인하십시오 .

inotify는 최신 리눅스에서 dnotify를 대체하고 (디렉토리 레벨 모니터링보다는 파일 레벨을 허용합니다).


답변

Tim Golden의 스크립트를 약간 해킹 한 후 다음과 같은 결과가 나타납니다.

import os

import win32file
import win32con

path_to_watch = "." # look at the current directory
file_to_watch = "test.txt" # look for changes to a file called test.txt

def ProcessNewData( newData ):
    print "Text added: %s"%newData

# Set up the bits we'll need for output
ACTIONS = {
  1 : "Created",
  2 : "Deleted",
  3 : "Updated",
  4 : "Renamed from something",
  5 : "Renamed to something"
}
FILE_LIST_DIRECTORY = 0x0001
hDir = win32file.CreateFile (
  path_to_watch,
  FILE_LIST_DIRECTORY,
  win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE,
  None,
  win32con.OPEN_EXISTING,
  win32con.FILE_FLAG_BACKUP_SEMANTICS,
  None
)

# Open the file we're interested in
a = open(file_to_watch, "r")

# Throw away any exising log data
a.read()

# Wait for new data and call ProcessNewData for each new chunk that's written
while 1:
  # Wait for a change to occur
  results = win32file.ReadDirectoryChangesW (
    hDir,
    1024,
    False,
    win32con.FILE_NOTIFY_CHANGE_LAST_WRITE,
    None,
    None
  )

  # For each change, check to see if it's updating the file we're interested in
  for action, file in results:
    full_filename = os.path.join (path_to_watch, file)
    #print file, ACTIONS.get (action, "Unknown")
    if file == file_to_watch:
        newText = a.read()
        if newText != "":
            ProcessNewData( newText )

아마도 더 많은 오류 검사와 관련이있을 수 있지만 로그 파일을보고 화면에 뱉기 전에 약간의 처리를 수행하면 잘 작동합니다.

여러분의 의견에 감사드립니다.