实时检测文件夹变化,及时同步文件到服务器python 脚本

55 篇文章 2 订阅

效果:

1.window开机自启动脚本。

2.自动生成配置文件到当前路径。

3.实时检测到文件夹变化,将文件通过到远程接口中,且文件进行分类备份到其他文件夹下。

4.实时发送心跳包,确保不会宕机。

5.重试机制@retry(已废除)

6.未解决BUG:实时删除会重复触发监测,引起modify,一次添加大量文件时会吃内存。

import datetime
import json
import os
import shutil
import time
from threading import Thread

import requests
import xlrd
from apscheduler.schedulers.blocking import BlockingScheduler
from requests_toolbelt import MultipartEncoder
from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer


# 读取文件夹下所有文件(不限级)
def readDir(dirPath):
    if dirPath[-1] == '/':
        print(u'文件夹路径末尾不能加/')
        return
    allFiles = []
    if os.path.isdir(dirPath):
        fileList = os.listdir(dirPath)
        for f in fileList:
            f = dirPath + '/' + f
            if os.path.isdir(f):
                subFiles = readDir(f)
                allFiles = subFiles + allFiles  # 合并当前目录与子目录的所有文件路径
            else:
                allFiles.append(f)
        return allFiles
    else:
        return 'Error,not a dir'


# 创建文件夹
def createFile(file_path):
    if os.path.exists(file_path) is False:
        os.makedirs(file_path)


# 推送文件到接口
def post_file(file_path, PUSH_URL):
    try:
        data = MultipartEncoder(fields={
            'propertyMessageXml': (os.path.basename(os.path.realpath(file_path)), open(file_path, 'rb'), 'text/xml')})
        r = requests.post(url=PUSH_URL, data=data,
                          headers={'Content-Type': data.content_type, 'Connection': 'close'})
        r.close()
        return r.content.decode('utf8')
    except:
        print("推送文件失败")


# 发送心跳包
def heartbeat(url):
    try:
        r = requests.post(url=url, data={'msg': datetime.datetime.now()})
        r.close()
    except:
        print("发送心跳包失败")


# 定时发送心跳包
def sendHeartbeat(url, HEARTBEAT_TIME):
    scheduler = BlockingScheduler()
    scheduler.add_job(heartbeat, 'interval', args=[url], seconds=int(HEARTBEAT_TIME))
    scheduler.start()


def handle_file(FOLD_PATH, PUSH_URL, BACK_FOLD_BASE, SYNC_TIME):
    try:
        file_path_list = readDir(FOLD_PATH)
        for file_path in file_path_list:
            # 推送文件
            result = post_file(file_path, PUSH_URL)
            print("推送结果:", result)
            # 对文件内容-进行分类备份
            global curve_name
            global test_time
            try:
                workbook = xlrd.open_workbook(file_path)
                sheet1 = workbook.sheets()[0]
                # 曲线名称
                curve_name = sheet1.row(1)[1].value  # 查看第2行第2列数据
                # 测试时间
                test_time = sheet1.row(1)[2].value.replace(" ", "").replace("/", "-").replace(":", "-")[
                            :10]  # 查看第2行第3列数据
            except BaseException as Message:
                print(Message)
                # 无法分类的文件
                BACK_FOLD = BACK_FOLD_BASE + '\\无法分类的文件'
                print(BACK_FOLD)
                createFile(BACK_FOLD)
                # 移动文件
                shutil.copy(file_path, BACK_FOLD)
                # 如果文件推送成功,就删除源文件,否则不删除,继续推送
                loads = json.loads(result)
                if loads['status'] == '1':
                    # 暂停几秒再删除,否则操作者不知道有没有把文件放进来
                    if SYNC_TIME:
                        time.sleep(int(SYNC_TIME))
                    os.remove(file_path)
                    continue

            # workbook.release_resources()
            # 创建文件夹
            BACK_FOLD = BACK_FOLD_BASE + '\\' + curve_name + '\\' + test_time
            print(BACK_FOLD)
            createFile(BACK_FOLD)
            # 移动文件
            shutil.copy(file_path, BACK_FOLD)
            # 如果文件推送成功,就删除源文件,否则不删除,继续推送
            loads = json.loads(result)
            if loads['status'] == '1':
                if SYNC_TIME:
                    time.sleep(int(SYNC_TIME))
                os.remove(file_path)
    except BaseException as Message:
        print(Message)


# 实时监测文件夹变化
class FileMonitorHandler(FileSystemEventHandler):

    def __init__(self, PUSH_URL, FOLD_PATH, BACK_FOLD_BASE, SYNC_TIME) -> None:
        self.PUSH_URL = PUSH_URL
        self.FOLD_PATH = FOLD_PATH
        self.BACK_FOLD_BASE = BACK_FOLD_BASE
        self.SYNC_TIME = SYNC_TIME
        super().__init__()

    # 重写文件改变函数,文件改变都会触发文件夹变化
    def on_modified(self, event):
        print("文件发生了变化")
        handle_file(self.FOLD_PATH, self.PUSH_URL, self.BACK_FOLD_BASE, self.SYNC_TIME)


# 初始化配置信息
def get_config():
    config = {}
    cwd = os.getcwd()
    # 当前路径是否有配置文件
    exists = os.path.exists(cwd + r'\config.txt')
    # 如果没有配置文件就创建一个,并赋予初始值
    if not exists:
        config['PUSH_URL'] = 'http://localhost:8088/java/testFilePush/upload'
        config['HEARTBEAT'] = 'http://localhost:8088/java/testFilePushHeartbeat/heartbeat'
        config['FOLD_PATH'] = r"D:\test"
        config['BACK_FOLD_BASE'] = r'D:\back'
        config['HEARTBEAT_TIME'] = 60
        config['SYNC_TIME'] = 3
        with open(cwd + r'\config.txt', mode='w', encoding='utf-8') as f:
            f.write(
                r"""
                # 推送地址
                PUSH_URL = http://localhost:8088/java/testFilePush/upload
                # 心跳地址
                HEARTBEAT = http://localhost:8088/java/testFilePushHeartbeat/heartbeat
                # 读取本地文件夹路径
                FOLD_PATH = D:\test
                # 备份基础路径
                BACK_FOLD_BASE = D:\back
                # 心跳周期
                HEARTBEAT_TIME = 60
                # 同步间隔(文件出现后多少秒同步删除)
                SYNC_TIME = 3
                """
            )
    # 如果有配置文件就直接读取
    else:
        with open(cwd + r'\config.txt', mode='r', encoding='utf-8') as f:
            line = f.readline()
            while line:
                # 去空格去换行符
                line = f.readline().replace(" ", "").replace('\n', '')
                if line is not None and not line.startswith('#'):
                    split = line.split('=')
                    if len(split) >= 2:
                        config[split[0]] = split[1]
    return config


if __name__ == '__main__':
    # 初始配置
    config = get_config()
    PUSH_URL = config['PUSH_URL']
    HEARTBEAT = config['HEARTBEAT']
    FOLD_PATH = config['FOLD_PATH']
    BACK_FOLD_BASE = config['BACK_FOLD_BASE']
    HEARTBEAT_TIME = config['HEARTBEAT_TIME']
    SYNC_TIME = config['SYNC_TIME']

    # 开个异步线程去执行心跳
    Thread(target=sendHeartbeat, args=[HEARTBEAT, HEARTBEAT_TIME]).start()

    # 实时文件夹监测
    event_handler = FileMonitorHandler(PUSH_URL, FOLD_PATH, BACK_FOLD_BASE, SYNC_TIME)
    observer = Observer()
    observer.schedule(event_handler, path=FOLD_PATH, recursive=True)  # recursive递归的
    observer.start()
    observer.join()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

文子阳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值