2011-10-21 8 views
1

Ex、Linux OSのいくつかのディレクトリでファイルイベントを削除して追加する必要があります。私はそれらのためのinotifyとPythonのラッパーのようなlibsを見つけましたが、もし私がos.listdir(path)毎秒出力を見なければならないか、またはそのようなタスクを達成するためのいくつかの方法がありますか?他の低レベルライブラリなしでPythonを使ってファイルシステムイベントを監視する

+3

これらのラッパーには何が問題なのですか? – eumiro

+1

私はちょうど何かextライブラリを使用することが許可されていないタスクがあります – User

答えて

1

出典:http://code.activestate.com/recipes/215418-watching-a-directory-tree-on-unix/

watch_directories()関数は、パスと呼び出し可能オブジェクトのリストを取り、その後、繰り返し削除されますか、その修正時刻が変更されたファイルを監視、それらのパスをルートディレクトリツリーを横断します。呼び出し可能オブジェクトは、変更されたファイルと削除されたファイルを含む2つのリストを渡されます。あなたがデーモンにジョブを送信するためにいくつかの方法が欲しいが、そのようなソケットやパイプなどのいくつかのIPCメカニズムを使用したくない場所

from __future__ import nested_scopes 

import os, time 

def watch_directories (paths, func, delay=1.0): 
    """(paths:[str], func:callable, delay:float) 
    Continuously monitors the paths and their subdirectories 
    for changes. If any files or directories are modified, 
    the callable 'func' is called with a list of the modified paths of both 
    files and directories. 'func' can return a Boolean value 
    for rescanning; if it returns True, the directory tree will be 
    rescanned without calling func() for any found changes. 
    (This is so func() can write changes into the tree and prevent itself 
    from being immediately called again.) 
    """ 

    # Basic principle: all_files is a dictionary mapping paths to 
    # modification times. We repeatedly crawl through the directory 
    # tree rooted at 'path', doing a stat() on each file and comparing 
    # the modification time. 

    all_files = {} 
    def f (unused, dirname, files): 
     # Traversal function for directories 
     for filename in files: 
      path = os.path.join(dirname, filename) 

      try: 
       t = os.stat(path) 
      except os.error: 
       # If a file has been deleted between os.path.walk() 
       # scanning the directory and now, we'll get an 
       # os.error here. Just ignore it -- we'll report 
       # the deletion on the next pass through the main loop. 
       continue 

      mtime = remaining_files.get(path) 
      if mtime is not None: 
       # Record this file as having been seen 
       del remaining_files[path] 
       # File's mtime has been changed since we last looked at it. 
       if t.st_mtime > mtime: 
        changed_list.append(path) 
      else: 
       # No recorded modification time, so it must be 
       # a brand new file. 
       changed_list.append(path) 

      # Record current mtime of file. 
      all_files[path] = t.st_mtime 

    # Main loop 
    rescan = False 
    while True: 
     changed_list = [] 
     remaining_files = all_files.copy() 
     all_files = {} 
     for path in paths: 
      os.path.walk(path, f, None) 
     removed_list = remaining_files.keys() 
     if rescan: 
      rescan = False 
     elif changed_list or removed_list: 
      rescan = func(changed_list, removed_list) 

     time.sleep(delay) 

if __name__ == '__main__': 
    def f (changed_files, removed_files): 
     print changed_files 
     print 'Removed', removed_files 

    watch_directories(['.'], f, 1) 

このレシピは便利です。代わりに、デーモンはサブミッションディレクトリに座って見ることができ、ファイルまたはディレクトリをサブミッションディレクトリにドロップすることによってジョブをサブミットすることができます。

ロックは考慮されません。 watch_directories()関数自体は本当にロックを行う必要はありません。 1回のパスで修正が欠けても、次のパスで修正されます。ただし、ジョブが監視対象のディレクトリに直接書き込まれている場合、呼び出し可能なオブジェクトは、ジョブファイルが半分だけ書き込まれている間に実行を開始することがあります。これを解決するには、ロックファイルを使用できます。呼び出し元は実行時にロックを取得しなければならず、サブミッターは新しいジョブを追加するときにロックを取得する必要があります。より簡単なアプローチは、rename()システムコールをアトミックにすることです。監視されていない一時ディレクトリにジョブを書き込み、ファイルが完成したらos.rename()を使用してsubmissionディレクトリに移動します。

関連する問題