2

内容を確認するためにときどきアクセスするディレクトリがあるため、このディレクトリとそのサブディレクトリ内のすべてのファイルのリスト パスを取得する次のコードを作成しました。

our_dir='c:\\mydocs'
walk=os.walk(our_dir)

for path, folders, files in walk:
    for f in files:
        file_path=os.path.join(path,f)
        print file_path

このディレクトリには 20 万以上のファイルがあり、頻繁にファイルの変更と追加が行われるため、コードの実行が完了すると、さらに多くのファイルが追加/変更されます。問題は、次のことをどのように行うかです。

  1. コードの初期実行を行い、初期実行開始時刻より前に作成/変更された、このディレクトリ内のすべてのファイル パスをリストします。
  2. 最初の実行中に追加/変更されたファイルを何らかの方法で保存します (最初の実行開始時間と最初の実行終了時間の間)。
  3. 後続のすべての実行で、現在の実行の前と最初の実行の終了時間の後、および現在の実行中 (現在の実行開始時間と現在の実行終了時間の間) に作成されたパスのみを一覧表示します。

これを行う方法について何か考えはありますか?ディレクトリを「監視/監視」しているのではなく、時々アクセスしていることを明確にしたいだけです。

4

1 に答える 1

3

これは非常に基本的な構造のアイデアです。各フォルダーは独自のスレッドを取得します。データを収集する「directoryHelper」クラスと、データを保存する「Directory」クラスの 2 つのクラスがあります。

スレッドは 1 回しか開始できないため、2 つのクラスが必要です。また、データを失うことなく、既にリストされているディレクトリに対して新しいスレッドを生成できる必要があります。

ルート ディレクトリは、指定されたパス ('C:\mydocs') をリストする Directory インスタンスになります。ファイルリストを self.files に保存し、そこに含まれるすべてのディレクトリに対して新しい Directory インスタンスを作成します (それらにアクセスできるように self.dirs に忘れずに)。

リフレッシュは時間を計ることができ、あなたが提案したようにディレクトリの変更日をチェックします。

私の考えを理解するのに役立つコードを次に示します。

class Helper(threading.Thread):
  def __init__(self, directory):
    super(Helper, self).__init__()
    self.directory = directory
    self.start()

  def run(self):
    for path, folders, files in os.walk(self.directory.path):
      for f in files:
          self.directory.files.append(os.path.join(path, f))

      for d in folders:
          self.directory.dirs.append(Directory(os.path.join(path, d), self.directory.interval, self.directory.do))

    self = None

class Directory(threading.Thread):
  def __init__(self, path, interval=5, do=None):
    super(Directory, self).__init__()
    self.path = path
    self.files, self.dirs = ([], [])
    self.interval = interval
    self.last_update = 0
    self.helper = None

    self.do = do # One flag to stop refreshing all instances
    if do == None:
      self.do = True

  def run(self):
    while self.do:
      self.refresh()
      time.sleep(self.interval)

  def refresh(self):
    # Only start a refresh if there self.helper is done and directory was changed
    if not self.helper and self.has_changed():
      self.last_update = int(time.time())
      self.helper = Helper(self)

  def has_changed(self):
    return int(os.path.getmtime(self.path)) > self.last_update

始めるにはこれで十分だと思います!

編集:実際に動作状態になるようにコードを少し変更しました。または、少なくともそうであることを願っています(テストしていません)!

編集 2: 私は実際に時間をかけてこれをテストし、修正しました。私は走った:

if __name__ == '__main__':
  root = Directory('/home/plg')
  root.refresh()
  root.helper.join()

  for d in [root] + root.dirs:
    for f in d.files:
      print f

と:

$ time python bin/dirmon.py | wc -l # wc -l == len(sys.stdout.readlines())
7805

real  0m0.078s
user  0m0.048s
sys 0m0.028s

これは、1 秒あたり 7805 / 0.078 = 100,064 ファイルです。悪くない!:)

編集 3 (最後の 1 つ!):「/」でテストを実行しました。最初の実行 (キャッシュなし): 147551 / 4.103 = 35,961 ファイル/秒

2 番目と 3 番目:

$ time python bin/dirmon.py | wc -l
147159

real  0m1.213s
user  0m0.940s
sys 0m0.272s
$ time python bin/dirmon.py | wc -l
147159

real  0m1.209s
user  0m0.928s
sys 0m0.284s

147551 / 1.213 = 1 秒あたり 121,641 ファイル

147551 / 1.209 = 122,044 ファイル/秒

于 2013-09-16T19:56:21.740 に答える