2009-07-22 15 views
5

Nella mia app ho bisogno di guardare una directory per i nuovi file. La quantità di traffico è molto grande e ci sarà un minimo di centinaia di nuovi file al secondo che appaiono. Attualmente sto usando un ciclo occupato con questo tipo di idea:Utilizzando select/poll/kqueue/kevent per guardare una directory per i nuovi file

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

Dopo l'esecuzione di profilazione che sto vedendo un sacco di tempo trascorso nel sonno, e mi chiedo se dovrei cambiare questa opzione per utilizzare il polling anziché.

Sto provando a utilizzare una delle classi disponibili in select per eseguire il polling della mia directory, ma non sono sicuro che funzioni effettivamente, o se sto semplicemente facendo qualcosa di sbagliato.

ottengo una fd per la mia directory con:

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

Ho poi provato diversi metodi per vedere quando le modifiche alla directory. A titolo di esempio, una delle cose che ho provato è stato:

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 

Perché poll() che agisce come se non ci sono più informazioni da leggere? Supponevo che avrebbe fatto solo se qualcosa fosse cambiato nella directory.

È quello che sto cercando di fare anche qui possibile?

In caso contrario, esiste un'alternativa migliore a while True: look for changes?

risposta

1

Dopo l'esecuzione di profilazione che sto vedendo un sacco di tempo trascorso nel sonno, e mi chiedo se dovessi cambiarlo per usare invece il polling.

Sembra che tu già fai polling sincrono, controllando lo stato ad intervalli regolari. Non preoccuparti del tempo "trascorso" in sleep, non consumerà il tempo della CPU. Passa semplicemente il controllo al sistema operativo che risveglia il processo dopo un timeout richiesto.

È possibile considerare il ciclo di eventi asincroni utilizzando una libreria che ascolta le notifiche di cambio del filesystem fornite dal sistema operativo, ma considera innanzitutto se offre vantaggi reali in questa particolare situazione.

3

Perché non utilizzare un wrapper Python per una delle librerie per il monitoraggio delle modifiche dei file, come gamin o inotify (cerca pyinotify, sono autorizzato a postare solo un hyperlink come nuovo utente ...): questo è sicuro essere più veloce e la roba di basso livello è già stato fatto a livello di C per te, utilizzando interfacce kernel ...

+0

Sto usando BSD, quindi inotify non è utilizzabile e sembra che Gamin non lo sia. – gdm

+0

Il gamin docs dice che è utilizzabile su FreeBSD ma usa una soluzione di polling meno ottimale - potrebbe essere comunque più veloce di qualsiasi altra cosa nonostante –

6

FreeBSD e quindi Mac OS X forniscono un analogo di inotify chiamato kqueue. Digitare man 2 kqueue su una macchina FreeBSD per ulteriori informazioni. Per kqueue su Freebsd hai PyKQueue disponibile al http://people.freebsd.org/~dwhite/PyKQueue/, sfortunatamente non viene mantenuto attivamente così il tuo chilometraggio può variare.

+1

Ah grazie per questo. Al momento della stesura di tutte le domande SO relative alla visione di una directory non si danno risposte a OS X. – Purrell

0

Si potrebbe voler dare un'occhiata a select.kqueue - Non l'ho usato ma Kqueue è l'interfaccia giusta per questo sotto BSD Credo in modo da poter monitorare file/directory e essere richiamati quando e solo quando cambiano

0

Ho scritto una libreria e uno strumento di shell che dovrebbe gestire questo per voi.

http://github.com/gorakhargosh/watchdog

Anche se, kqueue è un modo molto pesante per monitorare le directory mi farebbe piacere se è possibile testare e checkout eventuali prestazioni problemi che potrebbero verificarsi. Anche le patch sono benvenute.

HTH.