Usando select / votação / kqueue / kevent para assistir a um diretório para novos arquivos

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

Pergunta

No meu aplicativo eu preciso para assistir a um diretório para novos arquivos. A quantidade de tráfego é muito grande e não vão ter um mínimo de centenas de novos arquivos por segundo aparecendo. Atualmente estou usando um loop ocupado com esse tipo de idéia:

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

Depois de executar profiling eu estou vendo um monte de tempo gasto no sono, e eu estou querendo saber se eu deveria mudar isso para usar polling vez.

Eu estou tentando usar uma das classes disponíveis em select para consultar meu diretório, mas eu não tenho certeza se ele realmente funciona, ou se eu só estou fazendo errado.

Eu recebo um fd para o meu diretório com:

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

Eu, em seguida, tentou vários métodos para ver quando o diretório muda. Como exemplo, uma das coisas que eu tentei foi:

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

Por que é poll () agindo como não há mais informações para ler? Presumi que ele só faria isso se algo havia mudado no diretório.

É o que eu estou tentando fazer aqui mesmo possível?

Se não, existe alguma outra alternativa melhor para while True: look for changes?

Foi útil?

Solução

Depois de executar profiling eu estou vendo um monte de tempo gasto no sono, e eu estou querendo saber se eu deveria mudar isso para usar polling vez.

Parece que você já do polling síncrono, verificando o estado em intervalos regulares. Não se preocupe com o tempo "gasto" em sleep, não vai comer tempo de CPU. Ele só passa o controle para o sistema operacional que acorda o processo depois de um tempo limite requerido.

Você poderia considerar ciclo de eventos assíncrona usando uma biblioteca que escutas a sistema de arquivos notificações de alteração fornecidos pelo sistema operacional, mas considere primeiro se lhe dá qualquer benefício real nesta situação particular.

Outras dicas

FreeBSD e, assim, Mac OS X fornece um análogo da inotify chamado kqueue. Digite man 2 kqueue em uma máquina FreeBSD para obter mais informações. Para kqueue no FreeBSD você tem PyKQueue disponíveis em http://people.freebsd.org/~dwhite/ PyKQueue / , infelizmente, não é mantido ativamente assim que sua milhagem pode variar.

Por que não usar um invólucro de Python para uma das bibliotecas para monitorar as alterações de arquivos, como gamin ou inotify (procurar pyinotify, eu só estou autorizado a publicar um hiperlink como um novo usuário ...) - que é a certeza de ser mais rápido e as coisas de baixo nível já é feito no nível C para você , o uso do kernel interfaces de ...

Você pode querer ter um olhar para select.kqueue - Eu não usei, mas kqueue é a interface certa para isso sob BSD Eu acredito que você possa monitorar arquivos / diretórios e ser chamado de volta quando e somente quando eles mudam

Eu escrevi uma biblioteca e uma ferramenta de shell que deve lidar com isso para você.

http://github.com/gorakhargosh/watchdog

Embora, kqueue é uma maneira muito pesado para monitorar diretórios Eu apreciaria se você pode testar e check-out qualquer desempenho problemas que podem aparecer. Patches também são bem-vindos.

HTH.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top