Comment surveiller les modifications d'un fichier?

323

J'ai un fichier journal en cours d'écriture par un autre processus que je souhaite surveiller pour les modifications. Chaque fois qu'un changement se produit, j'aimerais lire les nouvelles données pour y effectuer un traitement.

Quelle est la meilleure façon de procéder? J'espérais qu'il y aurait une sorte de crochet de la bibliothèque PyWin32. J'ai trouvé la win32file.FindNextChangeNotificationfonction mais je ne sais pas comment lui demander de regarder un fichier spécifique.

Si quelqu'un a fait quelque chose comme ça, je serais vraiment reconnaissant d'entendre comment ...

[Modifier] J'aurais dû mentionner que je recherchais une solution qui ne nécessite pas d'interrogation.

[Modifier] Malédictions! Il semble que cela ne fonctionne pas sur un lecteur réseau mappé. Je suppose que Windows n'entend pas les mises à jour du fichier comme il le fait sur un disque local.

Jon Cage
la source
1
sous Linux, on pourrait utiliser stracedes writeappels de surveillance pour cela
test30
La réponse de @ simao utilise python-watchdog. Python-Watchdog a une excellente documentation -> voici un lien vers la documentation ["QuickStart"] qui fournit un exemple de code minimal qui surveille le répertoire de travail actuel.
Trevor Boyd Smith,

Réponses:

79

Avez-vous déjà consulté la documentation disponible sur http://timgolden.me.uk/python/win32_how_do_i/watch_directory_for_changes.html ? Si vous n'en avez besoin que pour travailler sous Windows, le 2ème exemple semble être exactement ce que vous voulez (si vous échangez le chemin du répertoire avec celui du fichier que vous voulez regarder).

Sinon, l'interrogation sera probablement la seule option vraiment indépendante de la plateforme.

Remarque: je n'ai essayé aucune de ces solutions.

Horst Gutmann
la source
5
Cette réponse est spécifique à Windows, mais il semble que certaines solutions multiplateformes à ce problème ont également été publiées ici.
Anderson Green
Existe-t-il une référence, si ce processus est plus lent que l'implémentation dans un langage natif comme c ++?
user1767754
Il est préférable d'insérer le contenu pertinent à partir des sources citées car elles peuvent devenir obsolètes.
Trilarion
2
(1.) à la fin de cette réponse est un avertissement fort ... "Je n'ai essayé aucune de ces solutions". (2.) cette réponse est plus ou moins une réponse "lien uniquement" (3.) la réponse mentionne "sondage" mais ne fournit rien d'ajoutant après cela ... alors que la réponse de @ Deestan fournit de bonnes informations sur le sondage
Trevor Boyd Smith,
283

Avez-vous essayé d'utiliser Watchdog ?

Bibliothèque Python API et utilitaires shell pour surveiller les événements du système de fichiers.

Surveillance des répertoires simplifiée avec

  • Une API multiplateforme.
  • Un outil shell pour exécuter des commandes en réponse aux changements de répertoire.

Commencez rapidement avec un exemple simple dans Quickstart ...

simao
la source
56
Installable avec easy_install? Vérifier. License gratuite? Vérifiez . Résout le problème sur les grandes plateformes? Vérifiez . J'approuve cette réponse. Seule remarque: l' exemple sur leur page de projet ne fonctionne pas tout de suite. Utilisez plutôt celui sur leur github .
Inaimathi
6
Nous utilisons un chien de garde. Nous pouvons passer à QFileSystemWatcher. Juste un avertissement - le chien de garde est bon mais loin d'être parfait sur toutes les plateformes (pour le moment). Chaque système d'exploitation a ses particularités. Donc, à moins que vous ne soyez déterminé à le rendre parfait, vous tirerez vos cheveux. Si vous cherchez à regarder une dizaine de fichiers, je voterais. La mise en cache du disque du système d'exploitation est très mature et Watchdog implique de toute façon d'interroger les API. C'est principalement pour regarder les énormes structures de dossiers à mon humble avis.
SilentSteel
3
Mon seul reproche avec le chien de garde est qu'il a de nombreuses dépendances. Moins que PyQt, bien sûr, mais cela ne fonctionne pas et se sent comme la solution minimale, la meilleure pratique, fait un travail et fait le bien.
AndreasT
1
@Denfromufa est-il correct ici? Watchdog verrouille-t-il vraiment les fichiers, de sorte qu'ils ne peuvent pas être modifiés simultanément pour que Watchdog les regarde? Je peux à peine croire que ce serait complètement inutile.
Michel Müller
1
@ MichelMüller Je viens de vérifier cet exemple (voir lien ci-dessous) et ça marche! Je ne sais pas ce qui n'allait pas avant, mais cette réponse ne donne aucun exemple. stackoverflow.com/a/18599427/2230844
denfromufa
93

Si l'interrogation vous convient, je regarderais simplement si la statistique du fichier "heure modifiée" change. Pour le lire:

os.stat(filename).st_mtime

(Notez également que la solution d'événement de modification native de Windows ne fonctionne pas dans toutes les circonstances, par exemple sur les lecteurs réseau.)

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...
Deestan
la source
1
Comment pouvez-vous faire cela sur un intervalle?
dopatraman
2
@dopatraman Voici comment procéder sur un intervalle `import sys import time pub = Monkey () while True: try: time.sleep (1) pub.watch () sauf KeyboardInterrupt: print ('\ nDone') break except : print (f'Erreur non gérée: {sys.exc_info () [0]} ') `
Vlad Bezden
Grande solution simple! J'ai ajouté un chèque pour le garder de signaler le fichier modifié lors de la première course: if self._cached_stamp is not None.
Noumenon
50

Si vous voulez une solution multiplateforme, vérifiez QFileSystemWatcher . Voici un exemple de code (non aseptisé):

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)
hipersayan_x
la source
6
Je pense que c'est probablement la meilleure réponse du groupe étant donné qu'ils a) s'appuient sur l'objet FileSystemwatcher de Win32 et ne peuvent pas être portés ou b) interrogent le fichier (ce qui est mauvais pour les performances et ne sera pas mis à l'échelle). C'est dommage que Python n'ait pas cette fonctionnalité intégrée car PyQt est une énorme dépendance si tout ce que vous utilisez est la classe QFileSystemWatcher.
CadentOrange
4
J'aime cette solution. Je voulais souligner que vous aurez besoin d'une instance QApplication pour que cela fonctionne, j'ai ajouté "app = QtGui.QApplication (sys.argv)" juste sous les importations, puis "app.exec_ ()" après les connexions de signal.
spencewah
Juste en testant cela sur une boîte Linux, je constate que la méthode directory_changed est appelée, mais pas file_changed.
Ken Kinder
@CadentOrange, si vous n'aimez pas la dépendance pyQt, le watchdogpackage est la bonne réponse
Mike Pennington
pourquoi ne pas l'utiliser PySidepour cela plutôt que PyQtpour une si petite utilisation.
Ciasto piekarz
29

Cela ne devrait pas fonctionner sur Windows (peut-être avec cygwin?), Mais pour les utilisateurs d'Unix, vous devriez utiliser l'appel système "fcntl". Voici un exemple en Python. C'est surtout le même code si vous avez besoin de l'écrire en C (mêmes noms de fonction)

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)
Maxime
la source
3
Fonctionne comme un charme avec le noyau Linux 2.6.31 sur un système de fichiers ext4 (sur Ubuntu 10.04), mais uniquement pour les répertoires - il déclenche une erreur IOError "not a directory" si je l'utilise avec un fichier.
David Underhill
1
GÉNIAL! Idem pour moi, fonctionne uniquement pour le répertoire et surveille les fichiers dans ce répertoire. Mais cela ne fonctionnera pas pour les fichiers modifiés dans les sous-répertoires, il semble donc que vous devez parcourir les sous-répertoires et les regarder tous. (ou y a-t-il une meilleure façon de le faire?)
lfagundes
20

Découvrez pyinotify .

inotify remplace dnotify (à partir d'une réponse antérieure) dans les nouveaux linux et permet une surveillance au niveau du fichier plutôt qu'au niveau du répertoire.

Michael Palmer
la source
5
Ne pas mettre un frein à cette réponse, mais après avoir lu cet article, je dirais que ce n'est peut-être pas une solution aussi glamour que la pensée. serpentine.com/blog/2008/01/04/why-you-should-not-use-pyinotify
NuclearPeon
1
pyinotify a beaucoup d'inconvénients, à partir d'une base de code très impythonique jusqu'à la consommation de mémoire. Mieux vaut chercher d'autres options ..
Tyto
13

Eh bien, après un peu de piratage du script de Tim Golden, j'ai ce qui suit qui semble assez bien fonctionner:

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 )

Cela pourrait probablement faire avec une charge plus de vérification des erreurs, mais pour simplement regarder un fichier journal et faire un traitement avant de le cracher à l'écran, cela fonctionne bien.

Merci à tous pour votre contribution - super trucs!

Jon Cage
la source
10

Pour regarder un seul fichier avec interrogation et dépendances minimales, voici un exemple entièrement étoffé, basé sur la réponse de Deestan (ci-dessus):

import os
import sys 
import time

class Watcher(object):
    running = True
    refresh_delay_secs = 1

    # Constructor
    def __init__(self, watch_file, call_func_on_change=None, *args, **kwargs):
        self._cached_stamp = 0
        self.filename = watch_file
        self.call_func_on_change = call_func_on_change
        self.args = args
        self.kwargs = kwargs

    # Look for changes
    def look(self):
        stamp = os.stat(self.filename).st_mtime
        if stamp != self._cached_stamp:
            self._cached_stamp = stamp
            # File has changed, so do something...
            print('File changed')
            if self.call_func_on_change is not None:
                self.call_func_on_change(*self.args, **self.kwargs)

    # Keep watching in a loop        
    def watch(self):
        while self.running: 
            try: 
                # Look for changes
                time.sleep(self.refresh_delay_secs) 
                self.look() 
            except KeyboardInterrupt: 
                print('\nDone') 
                break 
            except FileNotFoundError:
                # Action on file not found
                pass
            except: 
                print('Unhandled error: %s' % sys.exc_info()[0])

# Call this function each time a change happens
def custom_action(text):
    print(text)

watch_file = 'my_file.txt'

# watcher = Watcher(watch_file)  # simple
watcher = Watcher(watch_file, custom_action, text='yes, changed')  # also call custom action function
watcher.watch()  # start the watch going
4Oh4
la source
2
Vous pouvez créer watch_fileet créer des _cached_stamplistes, puis les parcourir en boucle for. Ne s'adapte pas vraiment bien à un grand nombre de fichiers
4Oh4
Cela ne déclenche-t-il pas l'action à chaque exécution? _cached_stamp est défini sur 0, puis comparé à os.stat (self.filename) .st_mtime. _cached_stamp doit être défini sur os.stat (self.filename) .st_mtime dans le constructeur, non?
Seanonymous
1
call_func_on_change()sera déclenché lors de la première exécution de look(), mais sera ensuite _cached_stampmis à jour, il ne sera donc pas déclenché à nouveau tant que la valeur des os.stat(self.filename).st_mtime. _cached_stampmodifications n'aura pas été modifiée .
4Oh4
1
Vous pouvez définir la valeur de _cached_stampdans le constructeur si vous ne voulez call_func_on_change()pas être appelé lors de la première exécution
4Oh4
J'ai utilisé votre script pour appeler une fonction lors d'un changement de fichier. Ma fonction ne prend aucun argument contrairement au vôtre. Je pensais que pour le faire fonctionner, je devais supprimer * args, ** kwargs Il semblait que (je n'ai mis que des lignes avec des changements): self.call_func_on_change(self) def custom_action(): watcher = Watcher(watch_file, custom_action())Mais cela n'a pas fonctionné. L'action n'a été appelée que lors de la première itération: le fichier a été modifié, le fichier a été modifié. Le fichier a été modifié. Le fichier a été modifié watcher = Watcher(watch_file, custom_action).
zwornik
7

Vérifiez ma réponse à une question similaire . Vous pouvez essayer la même boucle en Python. Cette page propose:

import time

while 1:
    where = file.tell()
    line = file.readline()
    if not line:
        time.sleep(1)
        file.seek(where)
    else:
        print line, # already has newline

Voir aussi la question tail () un fichier avec Python .

Bruno De Fraine
la source
Vous pouvez vous sys.stdout.write (ligne). Votre code ne fonctionne pas si le fichier est tronqué. Python a un fichier de fonction intégré ().
jfs
J'ai publié une version modifiée de votre code. Vous pouvez l'intégrer dans votre réponse si cela fonctionne pour vous.
jfs
7

La solution la plus simple pour moi est d'utiliser l'outil de surveillance watchmedo

Depuis https://pypi.python.org/pypi/watchdog, j'ai maintenant un processus qui recherche les fichiers sql dans un répertoire et les exécute si nécessaire.

watchmedo shell-command \
--patterns="*.sql" \
--recursive \
--command='~/Desktop/load_files_into_mysql_database.sh' \
.
redestructa
la source
6

Eh bien, puisque vous utilisez Python, vous pouvez simplement ouvrir un fichier et continuer à en lire des lignes.

f = open('file.log')

Si la ligne lue n'est pas vide , vous la traitez.

line = f.readline()
if line:
    // Do what you want with the line

Il se peut que vous manquiez de continuer à appeler readlineà l'EOF. Dans ce cas, il continuera à renvoyer une chaîne vide. Et lorsque quelque chose est ajouté au fichier journal, la lecture se poursuit à l'endroit où elle s'est arrêtée, selon vos besoins.

Si vous recherchez une solution qui utilise des événements ou une bibliothèque particulière, veuillez le spécifier dans votre question. Sinon, je pense que cette solution est très bien.

seuvitor
la source
6

Voici une version simplifiée du code de Kender qui semble faire la même astuce et n'importe pas le fichier entier:

# Check file for new data.

import time

f = open(r'c:\temp\test.txt', 'r')

while True:

    line = f.readline()
    if not line:
        time.sleep(1)
        print 'Nothing New'
    else:
        print 'Call Function: ', line
AlaXul
la source
6

Ceci est une autre modification du script de Tim Goldan qui s'exécute sur les types Unix et ajoute un simple observateur pour la modification de fichiers en utilisant un dict (file => time).

utilisation: quel que soit le nom.py path_to_dir_to_watch

#!/usr/bin/env python

import os, sys, time

def files_to_timestamp(path):
    files = [os.path.join(path, f) for f in os.listdir(path)]
    return dict ([(f, os.path.getmtime(f)) for f in files])

if __name__ == "__main__":

    path_to_watch = sys.argv[1]
    print('Watching {}..'.format(path_to_watch))

    before = files_to_timestamp(path_to_watch)

    while 1:
        time.sleep (2)
        after = files_to_timestamp(path_to_watch)

        added = [f for f in after.keys() if not f in before.keys()]
        removed = [f for f in before.keys() if not f in after.keys()]
        modified = []

        for f in before.keys():
            if not f in removed:
                if os.path.getmtime(f) != before.get(f):
                    modified.append(f)

        if added: print('Added: {}'.format(', '.join(added)))
        if removed: print('Removed: {}'.format(', '.join(removed)))
        if modified: print('Modified: {}'.format(', '.join(modified)))

        before = after
ronedg
la source
Mis à jour pour prendre en charge python3
ronedg
4

Comme vous pouvez le voir dans l'article de Tim Golden , pointé par Horst Gutmann , WIN32 est relativement complexe et surveille les répertoires, pas un seul fichier.

J'aimerais vous suggérer de regarder dans IronPython , qui est une implémentation de python .NET . Avec IronPython, vous pouvez utiliser toutes les fonctionnalités .NET - y compris

System.IO.FileSystemWatcher

Qui gère des fichiers uniques avec une interface d' événement simple .

gimel
la source
@Ciasto car alors vous devez avoir Iron Python disponible plutôt qu'une installation de base Python.
Jon Cage
1

Ceci est un exemple de vérification des modifications d'un fichier. Celui qui n'est peut-être pas la meilleure façon de le faire, mais c'est certainement un court chemin.

Outil pratique pour redémarrer l'application lorsque des modifications ont été apportées à la source. Je l'ai fait en jouant avec pygame afin que je puisse voir les effets se produire immédiatement après l'enregistrement du fichier.

Lorsqu'il est utilisé dans pygame, assurez-vous que le contenu de la boucle `` while '' est placé dans votre boucle de jeu, alias mise à jour ou autre. Sinon, votre application restera bloquée dans une boucle infinie et vous ne verrez pas la mise à jour de votre jeu.

file_size_stored = os.stat('neuron.py').st_size

  while True:
    try:
      file_size_current = os.stat('neuron.py').st_size
      if file_size_stored != file_size_current:
        restart_program()
    except: 
      pass

Au cas où vous voudriez le code de redémarrage que j'ai trouvé sur le web. C'est ici. (Pas pertinent pour la question, bien que cela puisse être utile)

def restart_program(): #restart application
    python = sys.executable
    os.execl(python, python, * sys.argv)

Amusez-vous à faire faire aux électrons ce que vous voulez qu'ils fassent.

Bassim Huis
la source
Il semble que l'utilisation à la .st_mtimeplace de .st_sizeserait plus fiable et un moyen tout aussi court de le faire, bien que l'OP ait indiqué qu'il ne voulait pas le faire via un sondage.
martineau
1
ACTIONS = {
  1 : "Created",
  2 : "Deleted",
  3 : "Updated",
  4 : "Renamed from something",
  5 : "Renamed to something"
}
FILE_LIST_DIRECTORY = 0x0001

class myThread (threading.Thread):
    def __init__(self, threadID, fileName, directory, origin):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.fileName = fileName
        self.daemon = True
        self.dir = directory
        self.originalFile = origin
    def run(self):
        startMonitor(self.fileName, self.dir, self.originalFile)

def startMonitor(fileMonitoring,dirPath,originalFile):
    hDir = win32file.CreateFile (
        dirPath,
        FILE_LIST_DIRECTORY,
        win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE,
        None,
        win32con.OPEN_EXISTING,
        win32con.FILE_FLAG_BACKUP_SEMANTICS,
        None
    )
    # 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_M in results:
            full_filename = os.path.join (dirPath, file_M)
            #print file, ACTIONS.get (action, "Unknown")
            if len(full_filename) == len(fileMonitoring) and action == 3:
                #copy to main file
                ...
lutin
la source
1

Voici un exemple conçu pour regarder des fichiers d'entrée qui n'écrivent pas plus d'une ligne par seconde mais généralement beaucoup moins. Le but est d'ajouter la dernière ligne (écriture la plus récente) au fichier de sortie spécifié. J'ai copié ceci à partir d'un de mes projets et j'ai juste supprimé toutes les lignes non pertinentes. Vous devrez remplir ou modifier les symboles manquants.

from PyQt5.QtCore import QFileSystemWatcher, QSettings, QThread
from ui_main_window import Ui_MainWindow   # Qt Creator gen'd 

class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        Ui_MainWindow.__init__(self)
        self._fileWatcher = QFileSystemWatcher()
        self._fileWatcher.fileChanged.connect(self.fileChanged)

    def fileChanged(self, filepath):
        QThread.msleep(300)    # Reqd on some machines, give chance for write to complete
        # ^^ About to test this, may need more sophisticated solution
        with open(filepath) as file:
            lastLine = list(file)[-1]
        destPath = self._filemap[filepath]['dest file']
        with open(destPath, 'a') as out_file:               # a= append
            out_file.writelines([lastLine])

Bien sûr, la classe QMainWindow englobante n'est pas strictement requise, c'est-à-dire. vous pouvez utiliser QFileSystemWatcher seul.


la source
0

Vous pouvez également utiliser une simple bibliothèque appelée repyt , voici un exemple:

repyt ./app.py
Rafal Enden
la source
0

Semble que personne n'a posté fswatch . Il s'agit d'un observateur de système de fichiers multiplateforme. Installez-le, exécutez-le et suivez les invites.

Je l'ai utilisé avec des programmes python et golang et ça marche.

Gus
la source
0

solution @ 4Oh4 associée un changement en douceur pour une liste de fichiers à regarder;

import os
import sys
import time

class Watcher(object):
    running = True
    refresh_delay_secs = 1

    # Constructor
    def __init__(self, watch_files, call_func_on_change=None, *args, **kwargs):
        self._cached_stamp = 0
        self._cached_stamp_files = {}
        self.filenames = watch_files
        self.call_func_on_change = call_func_on_change
        self.args = args
        self.kwargs = kwargs

    # Look for changes
    def look(self):
        for file in self.filenames:
            stamp = os.stat(file).st_mtime
            if not file in self._cached_stamp_files:
                self._cached_stamp_files[file] = 0
            if stamp != self._cached_stamp_files[file]:
                self._cached_stamp_files[file] = stamp
                # File has changed, so do something...
                file_to_read = open(file, 'r')
                value = file_to_read.read()
                print("value from file", value)
                file_to_read.seek(0)
                if self.call_func_on_change is not None:
                    self.call_func_on_change(*self.args, **self.kwargs)

    # Keep watching in a loop
    def watch(self):
        while self.running:
            try:
                # Look for changes
                time.sleep(self.refresh_delay_secs)
                self.look()
            except KeyboardInterrupt:
                print('\nDone')
                break
            except FileNotFoundError:
                # Action on file not found
                pass
            except Exception as e:
                print(e)
                print('Unhandled error: %s' % sys.exc_info()[0])

# Call this function each time a change happens
def custom_action(text):
    print(text)
    # pass

watch_files = ['/Users/mexekanez/my_file.txt', '/Users/mexekanez/my_file1.txt']

# watcher = Watcher(watch_file)  # simple



if __name__ == "__main__":
    watcher = Watcher(watch_files, custom_action, text='yes, changed')  # also call custom action function
    watcher.watch()  # start the watch going
mexekanez
la source
0

La solution la meilleure et la plus simple consiste à utiliser pygtail: https://pypi.python.org/pypi/pygtail

from pygtail import Pygtail
import sys

while True:
    for line in Pygtail("some.log"):
        sys.stdout.write(line)
George
la source
-2

Je ne connais aucune fonction spécifique à Windows. Vous pouvez essayer d'obtenir le hachage MD5 du fichier toutes les secondes / minutes / heures (selon la vitesse à laquelle vous en avez besoin) et le comparer au dernier hachage. Lorsqu'il diffère, vous savez que le fichier a été modifié et vous lisez les lignes les plus récentes.

scable
la source
-6

J'essaierais quelque chose comme ça.

    try:
            f = open(filePath)
    except IOError:
            print "No such file: %s" % filePath
            raw_input("Press Enter to close window")
    try:
            lines = f.readlines()
            while True:
                    line = f.readline()
                    try:
                            if not line:
                                    time.sleep(1)
                            else:
                                    functionThatAnalisesTheLine(line)
                    except Exception, e:
                            # handle the exception somehow (for example, log the trace) and raise the same exception again
                            raw_input("Press Enter to close window")
                            raise e
    finally:
            f.close()

La boucle vérifie s'il y a une ou plusieurs nouvelles lignes depuis la dernière lecture du fichier - si c'est le cas, elle est lue et transmise à la functionThatAnalisesTheLinefonction. Sinon, le script attend 1 seconde et recommence le processus.

kender
la source
4
-1: L'ouverture du fichier et la lecture des lignes ne sont pas une bonne idée lorsque les fichiers peuvent avoir une taille de 100 Mo. Vous devez également l'exécuter pour chaque fichier, ce qui serait mauvais lorsque vous souhaitez regarder des milliers de fichiers.
Jon Cage
1
Vraiment? Ouvrir le fichier pour les modifications?
Farsheed