Файл смотрите в каталоге с помощью Python, а затем отправляете данные с помощью POST-запроса при изменении файла.

Я хочу посмотреть два разных каталога для модификации файла excel (отметка времени), и после модификации я хочу вызвать один HTTP-запрос API к одной конечной точке, я уже написал код ниже, используя Python Watchdog и библиотеку запросов, но столкнулся с двумя ошибками в одном и том же .

Проблема 1: - событие (event.event_type == 'modified') срабатывает два раза при модификации одного файла, что приводит к отправке двух запросов данных. Итак, каков правильный тип события для наблюдения за изменением файла в сторожевой библиотеке, что сделает этот условный код истинным только один раз.

Проблема 2: - В классе «Наблюдатель» в функции «Пуск» я не могу присвоить значение 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() 

person shubham jain    schedule 13.09.2019    source источник


Ответы (2)


Проблема 1: событие "изменено" инициировано дважды

Эта проблема возникает из-за того, что при сохранении файла могут выполняться несколько операций, изменяются данные, а затем метаданные (последнее изменение...). С этим может быть сложно справиться в зависимости от того, что вам нужно, и частоты изменений, если есть много пользователей.

Сначала вы должны ограничить просматриваемые файлы, протестировав расширение, чтобы избежать временных файлов и всех других форматов. Затем я предлагаю сохранить время последнего изменения файла, чтобы иметь возможность сравнивать его между двумя событиями, и запускать вызов API, только если задержка превышает X секунд.

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()
person PRMoureu    schedule 13.09.2019
comment
Я решил проблему 2, а в проблеме 1: событие изменено дважды - кое-что работает нормально, теперь он выполняет код только один раз, но только первую модификацию в файле, когда я делаю вторую модификацию в любом из мой файл тоже через 5 или 10 минут, а затем он также был заблокирован в каком-то состоянии. как и в моем приведенном ниже коде, я просматриваю два каталога, поэтому он отлично работает для первого редактирования в обоих файлах, но когда я делаю вторую попытку для любого из этих файлов, он не дает мне никакого ответа или моего выполнения API. - person shubham jain; 16.09.2019
comment
Это модифицированный код после внесения изменений в соответствии с вашим предложением: 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')): sleep(5) if stats - self.files[event .src_path] › 1: df = pd.read_csv(self.path) - person shubham jain; 16.09.2019
comment
df1 = df.to_json(orient='records') print(df1) self.files[event.src_path] = статистика - person shubham jain; 16.09.2019
comment
Это условие дает мне 0,., при каждом запуске, даже через 10 или 15 минут,., из-за чего не запускается с третьей попытки: - if stats - self.files[event.src_path] › 1: - person shubham jain; 16.09.2019
comment
Хорошо, я могу проверить это позже. Пожалуйста, не могли бы вы обновить свой пост, чтобы добавить новый код? - person PRMoureu; 16.09.2019
comment
Я не уверен насчет статистики st_ctime, можете попробовать с st_mtime ? stats = os.stat(event.src_path).st_mtime - person PRMoureu; 16.09.2019
comment
да, что st_mtime работал отлично, я также понял это после публикации последнего кода вечером, я думал сообщить вам сейчас, но вы также найдете его сейчас, большое спасибо, что подошли, помогите мне,.,.,хорошего обучения с этим :) - person shubham jain; 16.09.2019
comment
Рад помочь вам в этом ;-) - person PRMoureu; 16.09.2019

Вы можете проверить модуль наблюдателя за изменением файлов по этой ссылке:

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

затем сделайте свою собственную обратную связь.

person hsyn    schedule 13.09.2019