5

私のアプリでは、ディレクトリで新しいファイルを監視する必要があります。トラフィックの量は非常に多く、1秒あたり最低数百の新しいファイルが表示されます。現在、私はこの種のアイデアでビジーループを使用しています:

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

プロファイリングを実行した後、睡眠中に多くの時間が費やされているのを見て、代わりにポーリングを使用するようにこれを変更する必要があるかどうか疑問に思っています。

で使用可能なクラスの1つを使用してディレクトリをポーリングしようとしていますselectが、それが実際に機能するのか、それとも間違っているだけなのかわかりません。

次のコマンドでディレクトリのfdを取得します。

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

次に、ディレクトリがいつ変更されるかを確認するために、いくつかの方法を試しました。例として、私が試したことの1つは次のとおりです。

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

読むべき情報がもっとあるようにpoll()が機能するのはなぜですか?ディレクトリ内で何かが変更された場合にのみ、それが行われると思いました。

私がここでやろうとしていることは可能ですか?

そうでない場合、他にもっと良い代替手段はありwhile True: look for changesますか?

4

6 に答える 6

6

FreeBSD、つまりMac OS Xは、kqueueと呼ばれるinotifyのアナログを提供します。詳細については、FreeBSDマシンでman2kqueueと入力してください。Freebsdのkqueueの場合、 http: //people.freebsd.org/~dwhite/PyKQueue/でPyKQueueを利用できますが、残念ながら積極的に保守されていないため、マイレージが異なる場合があります。

于 2009-09-22T07:24:01.353 に答える
3

gaminやinotifyなどのファイル変更を監視するためにライブラリの1つにPythonラッパーを使用してみませんか(pyinotifyを検索してください。新しいユーザーとして1つのハイパーリンクのみを投稿できます...)-これは確実に高速であり、低レベルのものは、カーネルインターフェイスを使用して、Cレベルですでに実行されています...

于 2009-07-24T15:24:38.210 に答える
1

プロファイリングを実行した後、睡眠中に多くの時間が費やされているのを見て、代わりにポーリングを使用するようにこれを変更する必要があるかどうか疑問に思っています。

定期的に状態を確認することで、すでに同期ポーリング行っているようです。「費やされた」時間を気にしないでくださいsleep。CPU時間を消費しません。要求されたタイムアウト後にプロセスをウェイクアップするオペレーティングシステムに制御を渡すだけです。

オペレーティングシステムによって提供されるファイルシステム変更通知をリッスンするライブラリを使用して非同期イベントループを検討することもできますが、この特定の状況で実際にメリットがあるかどうかを最初に検討してください。

于 2009-07-24T23:24:14.720 に答える
0

select.kqueueをご覧になることをお勧めします-私は使用していませんが、kqueueはBSDでこれに適したインターフェイスであるため、ファイル/ディレクトリを監視し、変更されたときにのみコールバックできると思います

于 2009-09-22T12:58:52.210 に答える
0

これを処理するライブラリとシェルツールを作成しました。

http://github.com/gorakhargosh/watchdog

ただし、kqueueはディレクトリを監視するための非常に重い方法ですが、発生する可能性のあるパフォーマンスの問題をテストしてチェックアウトできると幸いです。パッチも大歓迎です。

HTH。

于 2010-12-15T09:26:56.290 に答える
0

システムにselect.kqueue()がある場合、これを解決するのに非常に良い方法です。次に例を示します。

import os
import select

dn = '/tmp'
kq = select.kqueue()
fd = os.open(dn, os.O_DIRECT)

last = set(os.listdir(dn))

kevent = select.kevent(fd, filter=select.KQ_FILTER_VNODE,
    flags=select.KQ_EV_ADD | select.KQ_EV_CLEAR,
    fflags=select.KQ_NOTE_WRITE)

while True:
    if kq.control([kevent], 1):
        this = set(os.listdir(dn))

        added = list(this.difference(last))
        if added:
            print('  added: %s' % ' '.join(added))

        removed = list(last.difference(this))
        if removed:
            print('removed: %s' % ' '.join(removed))

        last = this
于 2020-03-26T22:19:04.523 に答える