4

ReadDirectoryChangesW APIを使用して、Pythonを使用したWindowsでの作成/削除/名前の変更についてディレクトリを監視しようとしています。これは私のコードであり、正常に機能しています。

results = win32file.ReadDirectoryChangesW(self.hDir, 8192, True, self.type, None,
                                           None)
for action, file in results:
    full_filename = os.path.join (self.source_path, file)
    if   action == 1:                                    # Created
        self.fileCreated(full_filename)
    elif action == 2:                                    # Deleted
        self.fileDeleted(full_filename)
    elif action == 3:                                    # Updated
        self.fileUpdated(full_filename)
    elif action == 4:                                    # Renamed from something
        renamed_file = full_filename
    elif action == 5:                                    # Renamed to something
        self.fileRenamed(renamed_file, full_filename)

ただし、監視対象のフォルダーをPythonまたはWindowsエクスプローラーから削除しようとすると、次のようになります。

WindowsError:[エラー32]ファイルが別のプロセスによって使用されているため、プロセスはファイルにアクセスできません:'c:\ users \ user \ appdata \ local \ temp \ new_dir'

これは理にかなっていると思いますが、どうすれば解決できますか?私のアプリケーションでは、ユーザーが監視フォルダーを削除できるようにする必要があるためです。非同期メソッドhttp://www.themacaque.com/?p=859の解決策を試しましたが、役に立ちませんでした。

前もって感謝します!

4

3 に答える 3

3

このブログ投稿から:

[ReadDirectoryChangesW]のもう1つの潜在的な落とし穴は、参照されているディレクトリ自体が現在「使用中」であるため、削除できないことです。ディレクトリ内のファイルを監視し、それでもディレクトリを削除できるようにするには、親ディレクトリとその子を監視する必要があります。

この投稿には、ReadDirectoryChangesWの適切な使用に関する詳細も記載されています。

于 2011-07-27T03:57:19.113 に答える
2

監視フォルダの削除は以下で可能ですReadDirectoryChangesW

JimBeveridgeによる「UnderstandingReadDirectoryChangesW-Part2」は、(Artomegusが述べたように)この問題の非常に良い背景ですが、FILE_SHARE_DELETE使用法を説明するステートメントは誤解を招く可能性があります。

私のテストでは、FILE_SHARE_DELETE実際に使用すると、監視対象フォルダーの削除/名前変更が可能になります。(つまり、唯一のオプションとして「親フォルダーを監視する」必要はありません。)

これが作業スニペットです(TimGoldenによるこの他の点では優れた「WatchaDirectoryforChanges」から大幅に編集および借用されています

# License is same as snippets on this page
# http://timgolden.me.uk/python/win32_how_do_i/watch_directory_for_changes.html
# In other words, bug Tim Golden to publish a license for his snippets
def windows_watch_path(watched_path):
    import win32file
    import win32con

    ACTIONS = {
        1 : "Created",
        2 : "Deleted",
        3 : "Updated",
        4 : "RenamedFrom",
        5 : "RenamedTo"
    }
    # Thanks to Claudio Grondi for the correct set of numbers
    FILE_LIST_DIRECTORY = 0x0001

    try:
        hDir = win32file.CreateFile (
            watched_path
            , FILE_LIST_DIRECTORY
            , win32con.FILE_SHARE_READ | 
              win32con.FILE_SHARE_WRITE | 
              win32con.FILE_SHARE_DELETE
            , None
            , win32con.OPEN_EXISTING
            , win32con.FILE_FLAG_BACKUP_SEMANTICS
            , None
        )
    except:
        # either it does not exist by this time, or some other issue... blah.
        # we'll just say "it 'changed' from 'some other expected state'"
        return [[watched_path, '', ACTIONS[2]]]

    results = win32file.ReadDirectoryChangesW (
        hDir,
        1024,
        True,
        win32con.FILE_NOTIFY_CHANGE_FILE_NAME |
        win32con.FILE_NOTIFY_CHANGE_DIR_NAME |
        win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES |
        win32con.FILE_NOTIFY_CHANGE_SIZE |
        win32con.FILE_NOTIFY_CHANGE_LAST_WRITE |
        win32con.FILE_NOTIFY_CHANGE_SECURITY,
        None,
        None
    )

    files_changed = []
    for action, fn in results:
        files_changed.append(
            [
                watched_path
                , fn
                , ACTIONS[action]
            ]
        )
        # print fullfn, ACTIONS.get(action, "Unknown")
    return files_changed
于 2012-09-10T04:16:31.033 に答える
0

わかりました。これを解決するのは簡単ではありません...私の場合(http://www.themacaque.com/?p=859)、ディレクトリの名前を変更したり、ディレクトリを削除したりできるという事実を無視しました。

ユーザーが監視フォルダーの名前を変更できるようにするためにできることは、パスの祖先でReadDirectoryChangesWを使用して、監視しているパスに従ってイベントを監視およびフィルター処理することです。イベントの処理を実行するためにツイストを使用してウォッチングを実行する新しい方法を実装しました。そのソリューションを使用すると、次の場合に祖先を攻撃する可能性があります。

  1. あなたのフォルダには、無視できるほど多くの兄弟がいません。興味のないイベントをフィルタリングするために、たくさんの操作を実行したくありません。
  2. ユーザーが祖先を削除できなくても問題ありません。

Windows上のUbuntuOneのコードでは、この問題に対処しており、確認できる優れたソリューションを実装しています。これは、ツイストリアクターのメインループのイベントに従って呼び出されるコールバックを使用してオブジェクトをフックできるようにするプロセッサを備えたLinuxでのpyinotifyの実装に少し続きます。そのコードを見てください、それはあなたを助けるかもしれません。

私のブログまたはirc(#ubuntuoneまたは#pyarのfreenode)で私が知っている最近の問題は、私のニックネームはmandelです;)

于 2011-07-30T15:10:36.197 に答える