本案例是,在工作中的实际需求,基于基本框架实现的, import中引入了很多框架封装好的组件,不能直接使用,课参考实现的一些开发思路。
需求: 将指定path下(包含子目录)的指定文件后缀和指定格式的文件内容,存储到数据库中,并能扩展其他文件后缀和其他格式的内容。
开发环境:python3.8 + JDK1.8 + MongoDB
分析:
1、分析需求:1)文件读取。2)写入数据库。3)导入文件的格式易扩展。
2、指定格式的 .def 文件导入到MongoDB指定的表单中。新建import_file.py , import_file2db.py 。
1)、import_file.py文件
定义基类 FileResources,执行对文件的相关操作:
a、遍历path下的文件列表 b、获取文件名 c、获取文件数据。
定义类 DefFileResources 继承 FileResources,执行 def 文件数据的格式化处理。
2)、import_file2db.py文件
定义基类 ImportDB ,初始化 dash, db_info , trace
定义类 ImportMessageFormat 继承 ImportDB , 将 .def 文件的内容保存或更新到数据库message_format中
3、扩展功能:
定义新类 newFileResources 继承 FileResources ,执行 新格式文件数据的格式化处理。
定义新类 newImport 继承 ImportDB ,将新格式文件数据保存到相关数据库表单中。
文件格式:
1、文件名: xx.def
2、内容格式:
## {dbName=None, version=1, collection=message_format} ##
"""""" DHCP: binary, big_endian { Op: byte, valueIn(1, 2, 3, 4, 5, 6), value(0x01); Htype: byte, value(0x01); Hlen: byte, valueRange(0, 16), value(0x06); Hops: byte, value(0x00); Xid: word, value(0x7b7c7b65); Secs: word, value(0x0000); Flags: word, value(0x8000);
""""""
import_file.py文件:
#!/usr/bin/env python # -*- coding: utf-8 -*- # @File : import_file.py # @Author: lianggl # @Time : 2020/6/30 10:26 import os import re from base.xdashboard import xDashboard, xTrace from dbrw.import_file2db import ImportMessageFormat from py_env import PyEnv
class FileResources(object): """ 对文件的相关操作 1、遍历path下的文件列表 2、获取文件名 3、获取文件数据 """ def __init__(self, path, filters, trace=None): self.path = path self.filters = filters if trace: self.trace = trace else: self.trace = xTrace() def scan_dir(self): """ 获取指定path下,后缀名为 filters 的文件列表 :param path: 文件所在目录 :param filters: 文件后缀 :return: 特定后缀名的文件名list """ # 获取指定目录的绝对路径 target_path = os.path.join(PyEnv.cur_dir(), self.path) self.trace.info(f'target_path: {target_path}') filesList = [] if target_path: # 遍历路径下, 后缀为指定 filters 的文件 for root, dirs, files in os.walk(target_path): if not files: continue for file in files: if os.path.splitext(file)[1] == self.filters: filesList.append(os.path.join(root, file)) # filesList.append(file) self.trace.info(f'filesList: {filesList}') else: self.trace.warning(f'Should spectify a relative path based on the root directory !') return filesList def get_file_name(self, file): if file: baseName = os.path.basename(file) self.trace.info(f'FileName is : {os.path.splitext(baseName)[0]}') return os.path.splitext(baseName)[0] def get_file_data(self, file): if file: with open(file, 'r', encoding='UTF-8') as f: fileData = f.read() self.trace.info(f'FileData is : {fileData}') return fileData class DefFileResources(FileResources): """ 导入 .def 文件 1、转换 def 文件的 header为 Dict 2、转换 def 文件的 fileData 为 Dict 3、调用类 ImportMessageFormat 实现文件写入 DB """ def __init__(self, path, filters='.def'): """ 初始化 dash , trace """ super().__init__(path, filters) self.dash = xDashboard(task_name='importFiles', create_mq=False) self.trace = self.dash.trace def fetch_file(self, file): """ 格式化header data 为 message_format 表单格式 :param file: :return: message_format表单的数据格式 """ docDict = {} fileName = self.get_file_name(file) docDict['fileName'] = fileName strBuffer = self.get_file_data(file) header = re.findall('\#\#[\s]*\{[\s\S]*\}[\s]*\#\#', strBuffer) self.trace.info(f'File Header : {header}') if header: headerDict = self.visitHeader(header) docDict['headerDict'] = headerDict else: self.trace.warning(f'Irregular header information: "" ... "" ') fileData = re.findall('\"{6}[\s]*[\s\S]*[\s]*\"{6}', strBuffer) if fileData: fileDataDict = self.visitFileData(fileData) docDict['fileData'] = fileDataDict return docDict # 格式化fileData def visitFileData(self, fileData): self.trace.info(f'File Data: {fileData}') if isinstance(fileData, list): result = fileData[0].strip() rstData = result.strip('\n')[6:-6] self.trace.info(f'File Data : {rstData}') return rstData # 格式化header def visitHeader(self, header): if isinstance(header, list): result = self.removeWhiteSpace(header[0]) rstDict = self.convert2Dict(result[2:-2]) return rstDict # 格式化header信息 def removeWhiteSpace(self, str): result = str.strip() result = result.strip('\n') result = result.replace(' ', '') result = result.replace('\r', '') result = result.replace('\n', '') return result # 转为dict格式 def convert2Dict(self,str): # {dbname = None, version = 1, collection =dict} self.trace.info(str) valueDict = dict() if re.search('^\{[\s\S]*\}$', str): str = str[1:-1] map = str.split(',') self.trace.info(map) for i in map: kv = i.split('=') self.trace.info(kv) valueDict[kv[0]] = kv[1] return valueDict def import_message_format(self): """ 将path目录下的 .def 文件导入到数据库 message_format 表单中 :param path: 文件所在的路径 :param filters: .def 文件后缀 :return: 是否成功 """ importMessageFormat = ImportMessageFormat(self.dash, self.trace) # count统计文件总数,count_success统计成功的数量 count = 0 count_success = 0 filesList = self.scan_dir() if len(filesList) > 0: count = len(filesList) for file in filesList: docDict = self.fetch_file(file) if importMessageFormat.save_data(docDict): count_success += 1 else: self.trace.info(f'File list is empty,Please check if the path parameters are correct, \ or Whether there is a .def file .') self.dump_result(count, count_success) return None # 导入 .def 文件结果统计 def dump_result(self, count, count_success): self.trace.info(f'*' * 50) self.trace.info(f'Total : {count} , Success : {count_success} , Error : {count - count_success}') self.trace.info(f'*' * 50) return None if __name__ == '__main__': # .def 文件须在 path 下 defFileResources = DefFileResources(path='smoketest/test', filters='.def') defFileResources.import_message_format()
import_file2db.py文件:
#!/usr/bin/env python # -*- coding: utf-8 -*- # @File : import_file2db.py # @Author: lianggl # @Time : 2020/6/30 10:50 from apis.protocol.parser.form.form_parser import ProtocolFormParser from base.xdashboard import xTrace from database.db_backup_inf import DBWriter class ImportDB(object): """ 将指定格式的数据写入到数据库中相应的表单中,执行save/update操作 """ def __init__(self, dash, trace): self.dash = dash self.db_info = DBWriter(self.dash.db.client) if trace: self.trace = trace else: self.trace = xTrace() def save_data(self, docDict): pass class ImportMessageFormat(ImportDB): """ 将 .def 文件的内容,save/update 到数据库的message_format表单中 """ def __init__(self, dash, trace): super().__init__(dash, trace) def save_data(self, docDict): fileName = docDict['fileName'] dbName = docDict['headerDict']['dbName'] collection = docDict['headerDict']['collection'] pcode = docDict['fileData'] try: jcode = ProtocolFormParser(debug=False).parse_doc(pcode).data doc = dict(name=fileName, pcode=pcode, jcode=jcode, desc='', proto_filter=list()) self.db_info.insert_update_one(dict(name=fileName), doc, collection) self.trace.info(f'File {fileName} save or update Success !!') return True except Exception as e: self.trace.warning(e) return False