En utilisant select / poll / kqueue / kevent pour regarder un répertoire pour les nouveaux fichiers

StackOverflow https://stackoverflow.com/questions/1165571

Question

Dans mon application, je dois regarder un répertoire pour les nouveaux fichiers. La quantité de trafic est très grand et il va y avoir un minimum de centaines de nouveaux fichiers par seconde apparition. Actuellement, je suis en utilisant une boucle occupé avec ce genre d'idée:

while True:
  time.sleep(0.2)
  if len(os.listdir('.')) > 0:
    # do stuff

Après le profilage en cours d'exécution, je vois beaucoup de temps passé dans le sommeil, et je me demande si je dois changer cela à utiliser au lieu polling.

Je suis en train d'utiliser l'une des classes disponibles dans select au sondage mon répertoire, mais je ne suis pas sûr si cela fonctionne réellement, ou si je fais juste mal.

Je reçois un fd pour mon répertoire avec:

fd = os.open('.', os.O_DIRECT)

J'ai ensuite essayé plusieurs méthodes pour voir quand les changements d'annuaire. À titre d'exemple, l'une des choses que j'ai essayé était:

poll = select.poll()
poll.register(fd, select.POLLIN)

poll.poll()  # returns (fd, 1) meaning 'ready to read'

os.read(fd, 4096) # prints largely gibberish but i can see that i'm pulling the files/folders contained in the directory at least

poll.poll()  # returns (fd, 1) again

os.read(fd, 4096) # empty string - no more data

Pourquoi est-poll () agit comme il y a plus d'informations à lire? Je suppose qu'il ne le ferait que si quelque chose avait changé dans le répertoire.

Est-ce que je suis en train de faire ici même possible?

Dans le cas contraire, est-il une autre alternative à une meilleure while True: look for changes?

Était-ce utile?

La solution

  

Après le profilage en cours d'exécution, je vois beaucoup de temps passé dans le sommeil, et je me demande si je dois changer cela à utiliser au lieu polling.

On dirait que vous avez déjà faire vote synchrone, en vérifiant l'état à intervalles réguliers. Ne vous inquiétez pas le temps « passé » dans sleep, il ne mangera pas le temps CPU. Il passe juste au contrôle du système d'exploitation qui réveille le processus après un délai d'attente requis.

Vous pourriez envisager de boucle d'événements asynchrone en utilisant une bibliothèque qui écoute les notifications de modification du système de fichiers fournis par le système d'exploitation, mais considérer d'abord si elle vous donne des avantages réels dans cette situation particulière.

Autres conseils

FreeBSD et donc Mac OS X fournissent un analogue de kqueue appelé inotify. Tapez man 2 kqueue sur une machine FreeBSD pour plus d'informations. Pour kqueue sur Freebsd vous PyKQueue disponible à http://people.freebsd.org/~dwhite/ PyKQueue / , malheureusement est pas activement maintenu de sorte que votre kilométrage peut varier.

Pourquoi ne pas utiliser un wrapper Python pour l'une des bibliothèques pour le fichier de suivi des changements, comme ou inotify gamin (recherche pyinotify, je ne le droit d'afficher un lien hypertexte comme un nouvel utilisateur ...) - qui est sûr d'être plus rapide et les choses de bas niveau est déjà fait au niveau C pour vous , en utilisant les interfaces du noyau ...

Vous pouvez jeter un oeil à select.kqueue - Je ne l'ai pas utilisé, mais kqueue est la bonne interface pour cette sous BSD, je crois que vous pouvez surveiller les fichiers / répertoires et être rappelé quand et seulement quand ils changent

J'ai écrit une bibliothèque et un outil shell qui doit gérer cela pour vous.

http://github.com/gorakhargosh/watchdog

Bien que, kqueue est un moyen très lourd pour surveiller les répertoires Je vous en serais reconnaissant si vous pouvez tester et extraira toute performance les problèmes que vous pourriez rencontrer. Les patchs sont également les bienvenus.

HTH.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top