1、利用windows api对文件系统进行监听
尝试1:利用FindFirstChangeNotificationA、WaitForMultipleObjects、FindNextChangeNotification组合
这一组合缺点是就api而言无法获取变更的文件名,还要自己遍历文件夹比对。放弃。
尝试2:CreateFileA、ReadDirectoryChangesW组合,完美的组合,可以获取到变更的文件名,唯一不足的是还要用一个函数来转换获取到的文件名(WideCharToMultiByte)。
2、关于python调用c语言。使
用distutils可以将c程序编译成pyd,然后倒入到python程序中调用。
3、由于GIL的关系
由于GIL的关系,在调用c程序时,解释器会被锁住,直到c调用结束才释放(也可以自己释放,函数组:PyEval_AcquireLock();PyEval_ReleaseLock();),在监听等待操纵系统通知的时候是阻塞的,锁住之后再被阻塞,程序就不动了,于是便利用popen来调用。在c程序中以printf来与python程序交互。(感谢RednaxelaFX)
#include <stdio.h> #include <stdlib.h> #include <windows.h> int main(int argcount, char** args) { if(argcount != 2){ return EXIT_SUCCESS; } char* path = args[1]; HANDLE hDir = CreateFileA(path, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); FILE_NOTIFY_INFORMATION Buffer[1024]; DWORD BytesReturned; int i = 0; if (ReadDirectoryChangesW(hDir, &Buffer, sizeof(Buffer), TRUE, FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_FILE_NAME, &BytesReturned, NULL, NULL)) { for (i = 0; i < BytesReturned; i++) { if (Buffer[i].FileNameLength > 0) { char* action = "_default_"; switch (Buffer[i].Action) { case FILE_ACTION_ADDED: action = "added"; break; case FILE_ACTION_REMOVED: action = "removed"; break; case FILE_ACTION_MODIFIED: action = "modified"; break; case FILE_ACTION_RENAMED_OLD_NAME: action = "renamed_old_name"; break; case FILE_ACTION_RENAMED_NEW_NAME: action = "renamed_new_name"; break; case FILE_ACTION_ADDED_STREAM: action = "ADDED_STREAM"; break; case FILE_ACTION_ID_NOT_TUNNELLED: action = "ID_NOT_TUNNELLED"; break; case FILE_ACTION_MODIFIED_STREAM: action = "MODIFIED_STREAM"; break; case FILE_ACTION_REMOVED_BY_DELETE: action = "REMOVED_BY_DELETE"; break; case FILE_ACTION_REMOVED_STREAM: action = "REMOVED_STREAM"; break; case FILE_ACTION_TUNNELLED_ID_COLLISION: action = "TUNNELLED_ID_COLLISION"; break; } char path[MAX_PATH]; WideCharToMultiByte(CP_ACP, 0, Buffer[i].FileName, Buffer[i].FileNameLength, path, sizeof(path), NULL, FALSE); printf("%s:%s", action, path); break; } } } return EXIT_SUCCESS; }
os.popen("FileSystemChangeListener.exe %s" % self.path).read()