使用 Python 在目录中监视文件,然后使用 POST 请求文件修改发送数据

File watch in the directory using Python and then send data using POST request on file modification

我想查看两个不同的目录以进行 excel 文件修改(时间戳),修改后我想向一个端点调用一个 API HTTP Post 请求,我已经使用 Python Watchdog 和 requests 库编写了以下代码,但同样面临两个错误。

问题 1:- 事件 (event.event_type == 'modified') 在一个文件修改时触发两次,导致发送两个 post 数据请求。那么在看门狗库中监视文件修改的正确事件类型是什么,这将使这个条件代码只为真一次。

问题 2:- 在 'Watcher' class 函数 'start' 中,我无法将 Handler() 值分配给 event_handler 变量。我在这里犯了什么错误?

请指导我解决此问题或任何其他更好的方法。提前谢谢你

    import time 
from time import sleep
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import json
import requests
import pandas as pd
import os
from collections import defaultdict

class Handler(FileSystemEventHandler):

    def __init__(self, path):
        super().__init__()
        self.path = path   
        self.files = defaultdict(lambda:0)     

    def on_modified(self, event):
        if event.is_directory:
            return None

        elif (event.event_type == 'modified' and event.src_path.endswith('.csv')):
                # api_url = 'http://10.166.72.3:8080/promo/summary?userId=abc'
                stats = os.stat(event.src_path).st_ctime
                sleep(5)
                if stats - self.files[event.src_path] > 1:
                    df = pd.read_csv(self.path)
                    df1 = df.to_json(orient='records')
                    df1.replace("\","")
                    print(df1)

        self.files[event.src_path] = stats
                #r = requests.post(url=api_url, json=df1)
                #print(r.status_code, r.reason, r.text)


class Watcher:

    def __init__(self, directory, handler):
        self.directory = directory
        self.handler = handler
        self.observer = Observer()

    def start(self):
        #event_handler = Handler()
        self.observer.schedule( self.handler, self.directory, recursive=True)
        self.observer.start()

    def stop(self):
        self.observer.stop()

    def join(self):
        self.observer.join()

if __name__ == '__main__': 

    handler1 = Handler('C:\Users\BPM_admin\Desktop\OCR_RPA\FirstOCR\Diageo\Output\InvoiceMasterData.csv')
    handler2 = Handler('C:\Users\BPM_admin\Desktop\OCR_RPA\SecondOCR\Diageo\Output\AgreementMasterData.csv')

    w1 = Watcher("C:\Users\BPM_admin\Desktop\OCR_RPA\FirstOCR\Diageo\Output", handler1) 
    w2 = Watcher("C:\Users\BPM_admin\Desktop\OCR_RPA\SecondOCR\Diageo\Output", handler2) 

    w1.start() 
    w2.start() 

    try:
       while True:
           time.sleep(5)
    except:
        w1.stop() 
        w2.stop() 
        print("Error")

    w1.join() 
    w2.join() 

您可以从此 link:

检查文件更改观察器模块

https://github.com/NVISO-BE/binsnitch

然后制作您自己的警报反馈。

问题 1:事件 "modified" 触发了两次

出现此问题是因为保存文件时可能会发生多个操作,更改数据,然后更改元数据(最后修改...)。如果有很多用户,根据您的需要和更改频率可能很难处理。

首先你应该通过测试扩展来限制观看的文件以避免临时文件和所有其他格式。然后我建议保存最后一次修改文件以便能够在两个事件之间进行比较,并且仅当延迟超过 X 秒时才触发 API 调用。

import os
from collections import defaultdict

class Handler(FileSystemEventHandler):

    def __init__(self):
        super().__init__()
        # this dict will store the filenames and the time
        self.files = defaultdict(lambda:0)

    def on_any_event(self, event):
        if event.is_directory:
            return None

        elif (event.event_type == 'modified' and 
              event.src_path.endswith(('.xls','.xlsx'))) :

            # here we get the last change timestamp 
            stats = os.stat(event.src_path).st_mtime

            # delay of 1 sec minimum between 2 changes
            # self.files[event.src_path] is set to 0 thanks to the defaultdict
            if stats - self.files[event.src_path] > 1: 
                print('api call with ', event.src_path)
                # do what you need

            # then update the time for this file
            self.files[event.src_path] = stats

问题 2:传递处理程序参数

实例化 Handler() 时出现错误,因为您在构造函数中创建了参数 path

class Handler(FileSystemEventHandler):

    def __init__(self, path):
        super().__init__()
        self.path = path        

你似乎没有在Handler里面使用它,也许你可以删除这个参数?否则只需给出你想要处理的路径:

def start(self):
    event_handler = Handler(self.directory) # or Handler() if you remove path
    self.observer.schedule(event_handler, self.directory, recursive=True)
    self.observer.start()