Python - 运行 文件夹变化时的函数

Python - run function when folder changes

我想 运行 每当我的文件夹发生变化时我的功能。这里要做的主要事情是规范化新文件,我们通过比较我的两个文件夹,包含规范化文件的文件夹和我们添加新文件的文件夹以及 return 我们的不匹配文件列表来做到这一点normalize函数会修改并放置在normalized的文件夹中。

这是我的代码:

def normalize(c):
    PATH = path_to_file 
    fileNames = os.listdir(PATH)

    fileNames = c
    for file in fileNames:
        sfm = pd.read_csv(PATH + file, delimiter = ';', parse_dates=[[0, 1]], skiprows = 3)
  # other instructions then rewrite my new dataframe in my normalized folder
sfm.to_csv('.\dirnormalized'+str(file[:-4])+'.csv', sep=';', index=False, header=True)

def comparison():
    PATH = path_to_file 
    PATH_norm = path_to_norm
    fileNames = os.listdir(PATH)
    files = os.listdir(PATH_norm)
    fileNames = [file for file in fileNames if '.csv' in file]
    files = [fl for fl in files if '.csv' in fl]
    diff = [x for x in fileNames if x not in files]
    return diff

def change():

    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s - %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S')
# path_to_file and word_file are the same the only difference is that in path_to_file we have a back slash in the end in order to acces the files one by one 
    path = word_file
    event_handler = LoggingEventHandler()
    observer = Observer()
    observer.schedule(event_handler, path, recursive=True)
    observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()

def process(): 
    if(change()):
        c = comparison()
        normalize(c)
if __name__ == "__main__":
    import os 
    import time
    import logging
    from watchdog.observers import Observer
    from watchdog.events import LoggingEventHandler

    process()

这里唯一的问题是在我的 process() 函数中 if() 指令似乎没有传递给其他指令,我可以看到何时添加新文件,这意味着何时发生修改但其他指令不会出现,它卡在 if() 上。

process() 的最后一行即 observer.join() 可能会阻塞线程以防止函数返回。

此外,控制让函数返回 None,导致 if 语句永远不会被执行。

查看 this 目录中的更改。

使用 MS ReadDirectoryChanges API,通过 pywin32 win32file 模块公开。

我们这里使用的方式是在阻塞模式下调用ReadDirectoryChangesW。

函数returns 一个二元组列表,每个元组代表一个动作和一个文件名。重命名总是给出一对二元组;其他复合动作也可能给出一个列表。

import os
import win32file
import win32con

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

path_to_watch = "."
hDir = win32file.CreateFile (
  path_to_watch,
  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
)
while 1:
  #
  # ReadDirectoryChangesW takes a previously-created
  # handle to a directory, a buffer size for results,
  # a flag to indicate whether to watch subtrees and
  # a filter of what changes to notify.
  #
  # NB Tim Juchcinski reports that he needed to up
  # the buffer size to be sure of picking up all
  # events when a large number of files were
  # deleted at once.
  #
  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
  )
  for action, file in results:
    full_filename = os.path.join (path_to_watch, file)
    print full_filename, ACTIONS.get (action, "Unknown")

通过一些编辑,这可以很容易地实现你想要的,因为利用了 winApi,它可能不太容易出错。

谢谢蒂姆·戈登。