数据库:Hive转Presto(五)

此篇将所有代码都补充完了,之前发现有的代码写错了,以这篇为准,以下为完整代码,如果发现我有什么考虑不周的地方,可以评论提建议,感谢。代码是想哪写哪,可能比较繁琐,还需要优化。

import re
import os
import tkinter.filedialog
from tkinter import *class Hive2Presto:def __int__(self):self.t_funcs = ['substr', 'nvl', 'substring', 'unix_timestamp'] + \['to_date', 'concat', 'sum', 'avg', 'abs', 'year', 'month', 'ceiling', 'floor']self.time_funcs = ['date_add', 'datediff', 'add_months', 'date_sub']self.funcs = self.t_funcs + self.time_funcsself.current_path = os.path.abspath(__file__)self.dir = os.path.dirname(self.current_path)self.result = []self.error = []self.filename = ''def main(self):self.root = Tk()self.root.config(bg='#ff741d')  # 背景颜色设置为公司主题色^_^self.root.title('Hive转Presto')self.win_width = 550self.win_height = 500self.screen_width = self.root.winfo_screenwidth()self.screen_height = self.root.winfo_screenheight()self.x = (self.screen_width - self.win_width) // 2self.y = (self.screen_height - self.win_height) // 2self.root.geometry(f'{self.win_width}x{self.win_height}+{self.x}+{self.y}')font = ('楷体', 11)self.button = Button(self.root, text='转换', command=self.trans, bg='#ffcc8c', font=font, anchor='e')self.button.grid(row=0, column=0, padx=100, pady=10, sticky=W)self.file_button = Button(self.root, text='选择文件', command=self.choose_file, bg='#ffcc8c', font=font,anchor='e')self.file_button.grid(row=0, column=1, padx=0, pady=10, sticky=W)self.entry = Entry(self.root, width=65, font=font)self.entry.insert(0, '输入Hive代码')self.entry.grid(row=1, column=0, padx=10, pady=10, columnspan=2)self.entry.bind('<Button-1>', self.delete_text)self.text = Text(self.root, width=75, height=20)self.text.grid(row=2, column=0, padx=10, pady=10, columnspan=2)self.des_label = Label(self.root, text='可以复制结果,也有生成的文件,与选取的文件同文件夹', bg='#ffcc8c',font=('楷体', 10))self.des_label.grid(row=3, column=0, padx=10, pady=10, columnspan=2)s = ''for i in range(0, (n := len(self.funcs)), 4):if i + 4 <= n:s += ','.join(self.funcs[i:i + 4]) + '\n'else:s += ','.join(self.funcs[i:]) + '\n's = s[:-1]self.des_label1 = Label(self.root, text=s, bg='#ffcc8c',font=('楷体', 10))self.des_label1.grid(row=4, column=0, padx=10, pady=10, columnspan=2)self.root.columnconfigure(0, minsize=10)self.root.columnconfigure(1, minsize=10)self.root.columnconfigure(0, pad=5)self.root.mainloop()def replace_func(self, s, res):"""把搜索到函数整体取出来,处理括号中的参数:param s::param res::return:"""for f in res:f1 = f.replace('\n', '').strip()f1 = re.sub(r'(\(s*)', '(', f1)# 搜索括号里的字符串if re.findall(r'(\w+)\(', f1):func_name = re.findall(r'(\w+)\(', f1)[0].strip()else:continuetry:if 'date_add' == func_name.lower():date, date_num = self.extact_func(f1, func_name)s_n = f"date_add('day',{date_num},cast(substr(cast{date} as varchar,1,10) as date))"s = s.replace(f, s_n)elif 'datediff' == func_name.lower():date1, date2 = self.extact_func(f1, func_name)s_n = f"date_add('day',{date2},cast(substr(cast{date1} as varchar,1,10) as date),cast(substr(cast{date1} as varchar),1,10) as date))"s = s.replace(f, s_n)elif 'nvl' == func_name.lower():s1, s2 = self.extact_func(f1, func_name)s_n = f"coalesce({s1},{s2})"s = s.replace(f, s_n)elif 'substr' == func_name.lower():date, start, end = self.extact_func(f1, func_name)s_n = f"substr(cast({date} as varchar),{start},{end}"s = s.replace(f, s_n)elif 'substring' == func_name.lower():date, start, end = self.extact_func(f1, func_name)s_n = f"substring(cast({date} as varchar),{start},{end}"s = s.replace(f, s_n)elif 'unit_timestamp' == func_name.lower():date = self.extact_func(f1, func_name)[0]s_n = f"to_unixtime(cast({date} as timestanp))"s = s.replace(f, s_n)elif 'to_date' == func_name.lower():date = self.extact_func(f1, func_name)[0]s_n = f"cast({date} as date)"s = s.replace(f, s_n)elif 'concat' == func_name.lower():res = self.extact_func(f1, func_name)[0]s_n = f'concat('for r in res:r = r.strip().replace('\n', '')s_n += f"cast({r} as varchar),"s_n = s_n[:-1] + ')'s = s.replace(f, s_n)elif 'sum' == func_name.lower():if 'unix_timestamp' in f1 or 'to_unixtime' in f1:continuess = self.extact_func(f1, func_name)[0]if 'if(' in ss.replace(' ', ''):continues = self.func_trans(f, f1, func_name, ss, s)elif 'avg' == func_name.lower():if 'unix_timestamp' in f1 or 'to_unixtime' in f1:continuess = self.extact_func(f1, func_name)[0]if 'if(' in ss.replace(' ', ''):continues = self.func_trans(f, f1, func_name, ss, s)elif 'abs' == func_name.lower():if 'unix_timestamp' in f1 or 'to_unixtime' in f1:continuess = self.extact_func(f1, func_name)[0]if 'if(' in ss.replace(' ', ''):continues = self.func_trans(f, f1, func_name, ss, s)elif 'ceiling' == func_name.lower():if 'unix_timestamp' in f1 or 'to_unixtime' in f1:continuess = self.extact_func(f1, func_name)[0]if 'if(' in ss.replace(' ', ''):continues = self.func_trans(f, f1, func_name, ss, s)elif 'floor' == func_name.lower():if 'unix_timestamp' in f1 or 'to_unixtime' in f1:continuess = self.extact_func(f1, func_name)[0]if 'if(' in ss.replace(' ', ''):continues = self.func_trans(f, f1, func_name, ss, s)elif 'year' == func_name.lower():date = self.extact_func(f1, func_name)[0]s_n = f"year(cast(substr(cast({date} as varchar,1,10) as date))"s = s.replace(f, s_n)elif 'month' == func_name.lower():date = self.extact_func(f1, func_name)[0]s_n = f"month(cast(substr(cast({date} as varchar,1,10) as date))"s = s.replace(f, s_n)elif 'date_sub' == func_name.lower():date, date_num = self.extact_func(f1, func_name)s_n = f"date_add('day',-{date_num},cast(substr(cast{date} as varchar,1,10) as date))"s = s.replace(f, s_n)except:self.error.append(f"源代码中{func_name}函数参数输入可能有错误,具体为:{f1}")continueif self.error:self.entry.delete(0, END)self.text.delete("1.0", END)self.text.insert("end", f"{s}")self.error.insert(0, '转换失败,有部分没有转成功\n')root_ex = Tk()root_ex.title('错误')win_width = 600win_height = 200screen_width = root_ex.winfo_screenwidth()screen_height = root_ex.winfo_screenheight()x = (screen_width - win_width) // 2y = (screen_height - win_height) // 2root_ex.geometry(f'{win_width}x{win_height}+{x}+{y}')label_ex = Label(root_ex, text="\n".join(self.error), font=("楷体", 10))label_ex.pack()root_ex.mainloop()return sdef func_trans(self, f, f1, func_name, ss, s):if not ('+' in ss or '-' in ss or '*' in ss or '/' in ss):date = self.extact_func(f1, func_name)[0]s_n = f'{func_name}(cast{date} as double))'s = s.replace(f, s_n)else:res1 = self.mysplit(f1)s_n = fn = len(s_n)for item in res1:if any(c.isalpha() for c in item.replace(' ', '')):idxs = s_n.find(item)idxs = [idxs] if type(idxs) != list else idxsfor idx in idxs:if idx + len(item) + 3 <= n:if not 'as' in s_n[idx:idx + len(item) + 4]:s_n = re.sub(rf'\b{item}\b', f'cast({item} as double)', s_n)else:s_n = re.sub(rf'\b{item}\b', f'cast({item} as double)', s_n)s = s.replace(f, s_n)return sdef choose_file(self):"""如果代码太多,从text中输入会很卡,直接选择代码文件输入会很快:return:"""self.filename = tkinter.filedialog.askopenfilename()if '/' in self.filename:self.filename = self.filename.replace('/', '\\')self.entry.delete(0, END)self.entry.insert(0, self.filename)def findvar(self, ss):"""搜索与计算有关的字段:param ss::return:"""global r1b = ['+', '-', '*', '/', '=', '!=', '>', '<', '<=', '>=', '<>']result1 = []result2 = []result1_n = []result2_n = []res_ops = []res1_ops = []res_adj = []res1_adj = []for op in b:s_temp1 = ss.replace('\n', ' ')s_temp2 = ss.replace('\n', ' ')s_temp3 = ss.replace('\n', ' ')if op == '/' or op == '=':op = opelif op == '+' or op == '-' or op == '*' or op == '>' or op == '<':op = f'\\{op[0]}'else:op = f'\\{op[0]}\\{op[1]}'parttern = f'\s*-*\d+\s*{op}\s*\w+|' + f'\s*-*\d+\.\s*{op}\s*\w+\.\s*\w+|' \+ f'\s*\w+\.\s*\w+\s*{op}\s*\w+\.\s*\w+|' + f'\s*\w+\s*{op}\s*\w+\.\s*\w+|' \+ f'\s*\w+\.\s*\w+\s*{op}\s*\w+|' + f'\s*\w+\s*{op}\s*\w+'parttern1 = f'\s*\)+\s*{op}\s*\w+|' + f'\s*\)+\s*{op}\s*\w+\.\s*\w+|' \+ f'\s*\w+\s*{op}\s*\(+|' + f'f\s*\w+\.\s*{op}\s*\(+'parttern2 = f'\s*\w+\s*{op}\s*\w+|' + f'\s*\w+\s*{op}\s*\w+\.\s*\w+|' \+ f'\s*\w+\s*{op}\s*\w+|' + f'f\s*\w+\.\s*{op}\s*\w+'while True:res = re.findall(parttern, s_temp1)if not res:breakresult2.extend(res)for r in res:r1 = r.replace(' ', '').split(f'op')result1.append(r1)res_ops.append(f'{op}')res_adj.append(False)s_temp1 = s_temp1.replace(f'{r1[0]}', '')# 搜索带括号的计算if op == '+' or op == '-' or op == '*' or op == '/':while True:res = re.findall(parttern1, s_temp2)if not res:breakresult2.extend(res)for r in res:r1 = r.replace(' ', '').split(f'{op}')result1.append(r1)res_ops.append(f'{op}')res_adj.append(False)tem = r1[0] if r1[0].strip() not in ['(', ')'] else r1[1]s_temp2 = s_temp2.replace(f'{tem}', '')else:res = re.findall(parttern2, s_temp3)result2.extend(res)for r in res:r1 = r.replace(' ', '').split(f'{op}')result1.append(r1)res_ops.append(f'{op}')res_adj.append(True)str_ = re.findall(r'\'([^\']*)\'', ss)str_ = list(set(str_))str_ = [v.rstrip(' \n') for v in str_]for i, fun in enumerate(result1):flag = 0for item in fun:if any(item.strip() in v for v in str_) or any(item.strip() == v for v in self.t_funcs):breakflag += 1if flag == 2 and result1[i] not in result1_n:result1_n.append(result1[i])result2_n.append(result2[i])res1_ops.append(res_ops[i])adj = result1[i][0] in self.time_funcs or result1[i][0] in self.time_funcsres1_adj.append(adj)if result1_n:z = zip(result1_n, result2_n, res1_ops, res1_adj)z1 = sorted(z, key=lambda x: len(x[1].replace(' ', '')), reverse=True)result1_n, result2_n, res1_ops, res1_adj = zip(*z1)return result1_n, result2_n, res1_ops, res1_adjdef mysplit(self, s):"""分割字段:param s::return:"""s = s.strip().replace(')', '').replace('(', '')b = ['+', '-', '*', '/']res = [s]result = []for op in b:n_res = []for item in res:n_res.extend(item.split(op))res = n_resfor item in res:if ' as ' not in item:result.append(re.findall(r'^[\w+_*]+$', item.replace(' ', ''))[0])result = list(set(res))return resultdef extact_func(self, s, func_name):res = []s = s[:-1].replace(f'{func_name}(', '', 1)com_idx = [i for i, v in enumerate(s) if v == ',']jd_com_idx = []for i in com_idx:s1 = s[0:i]if s1.count('(') == s1.count(')'):jd_com_idx.append(i)jd_com_idx.append(len(s))jd_com_idx.insert(0, -1)for i in range(1, len(jd_com_idx)):res.append(s[jd_com_idx[i - 1] + 1:jd_com_idx[i]])return resdef sort_funcs(self, li):li = sorted(li, key=lambda x: x.count('('), reverse=True)li_n = []for l in li:li_n.append(l)return li_ndef delete_text(self, event):self.entry.delete(0, END)self.filename = ''def trans(self):if self.filename:data = open(self.filename, 'r', encoding='utf-8').readlines()self.folder_path = os.path.dirname(self.filename)file_res = self.folder_path + r'\hive转presto_res.sql'os.startfile(f'{self.folder_path}')else:data = self.entry.get().split('\n')file_res = self.dir + r'\hive转presto_res.sql'data_n = []for s in data:if not s.rstrip(' \n'):continueif '”' in s:s = s.replace('“', '')if ',' in s:s = s.replace(',', ',')if '(' in s:s = s.replace('(', '(')if ')' in s:s = s.replace(')', ')')if (idx := s.find('--')) == -1:data_n.append(s + '\n')else:data_n.append(s[:idx] + '\n')data = ''.join(data_n)res1, res2, ops, adj = self.findvar(data)for i, ss in enumerate(res1):s_n = res2[i]s_n1 = res2[i]s_n2 = res2[i]s_t = res2[i]flag = 0for elem in ss:elem1 = elem.replace(' ', '')if any(c.isalpha() for c in elem1):if ops[i] in ['=', '!=', '>', '<', '<=', '>=', '<>']:if adj[i]:if elem1 not in self.time_funcs:s_n = re.sub(rf'\b{elem}\b', f'cast(substr({elem1},1,10) as date', s_n)continueelse:continueif any(op in s_t for op in ['+', '-', '*', '/']):s_n = re.sub(rf'\b{elem}\b', f'cast({elem1} as double)', s_n)else:s_n = re.sub(rf'\b{elem}\b', f'cast({elem1} as varchar)', s_n)else:if elem.strip() not in ['(', ')']:s_n = re.sub(rf'\b{elem}\b', f'cast({elem1} as double)', s_n)flag += 1data = data.replace(res2[i].strip(), s_n)if flag == 2:if any(op in s_t for op in ['+', '-', '*', '/']):s_n1 = re.sub(rf'\b{ss[0]}\b', f'cast({ss[0]} as double)', s_n)s_n2 = re.sub(rf'\b{ss[1]}\b', f'cast({ss[1]} as double)', s_n)else:s_n1 = re.sub(rf'\b{ss[0]}\b', f'cast({ss[0]} as varchar)', s_n)s_n2 = re.sub(rf'\b{ss[1]}\b', f'cast({ss[1]} as varchar)', s_n)data = data.replace(s_n1, s_n)data = data.replace(s_n2, s_n)self.error = []self.result = []for func_name in self.funcs:r = [m.start() for m in re.finditer(func_name, data.lower())]for idx in r:n = 1while True:s = data[idx:idx + n]if (s.count(')') == s.count('(') and s.count(')') != 0) and idx + n > len(data):breakn += 1if s not in self.result and s.rstrip(' \n')[len(func_name)] == '(':self.result.append(s)self.result = self.sort_funcs(self.result)res = self.replace_func(data, self.result)res_new = []for r in res.split('\n'):if r.rstrip(' \n'):res_new.append(r)res_new = '\n'.join(res_new)self.text.delete("1.0", END)self.text.insert("end", f'{res_new}')with open(file_res, 'w', encoding='utf-8') as f:f.write(res_new)if __name__ == '__main__':pro = Hive2Presto()pro.__int__()pro.main()

效果如下所示:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/103142.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Maven - 5 分钟快速通关

目录 一、Maven 1.1、 基础语法 1.2、聚合 1.3、继承 1.4、自定义属性 一、Maven 1.1、 基础语法 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/…

MVVM 与 MVC区别和应用场景?

MVVM 和 MVC 1. MVC2. MVVM 1. MVC MVC 是 Model View Controller 的缩写 Model&#xff1a;模型层&#xff0c;是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。View&#xff1a;视图层&#xff0c;用户界面渲染逻辑&#xff0c;通常视图…

C#(Csharp)我的基础教程(三)(我的菜鸟教程笔记)-控件对象与窗体容器集合(Control)的探究与学习

目录 1、窗体类&#xff08;主代码文件窗体设计器后台代码文件&#xff09;2、控件对象与窗体容器集合&#xff08;Control&#xff09; 1、窗体类&#xff08;主代码文件窗体设计器后台代码文件&#xff09; 主窗体对象的创建&#xff1a;在Program类里面&#xff1a; Appli…

Spring Boot中的JdbcTemplate是什么,如何使用

Spring Boot中的JdbcTemplate是什么&#xff0c;如何使用 Spring Boot是一个流行的Java应用程序开发框架&#xff0c;它简化了Java应用程序的开发过程&#xff0c;并提供了丰富的功能和工具。在Spring Boot中&#xff0c;JdbcTemplate是一个强大的数据库访问工具&#xff0c;它…

【Python】PaddleOCR文字识别国产之光 从安装到pycharm中测试 (保姆级图文)

目录 官方项目地址Python环境搭建&#xff08;也就是使用Anaconda的python&#xff09;1. 安装Anaconda1. 打开终端并创建conda环境 安装PaddlePaddle&#xff08;CPU演示&#xff09;安装PaddleOCR whl包如果安装shapely库报错&#xff08;我没有报错&#xff0c;其他类似库安…

01 初识FPGA

01 初识FPGA 一.FPGA是什么 FPGA&#xff08;Filed Programmable Gate Array&#xff09;&#xff0c;现场可编程门阵列&#xff0c;一种以数字电路为主的集成芯片&#xff0c;属于可编程逻辑器件PLD的一种。 1.1 两大巨头 Xilinx(赛灵思)Altera&#xff08;阿尔特拉&#…

VPN基础

1.VPN简介 VPN即虚拟专用网&#xff0c;泛指通过VPN技术在公用网络上构建的虚拟专用网络。VPN用户在此虚拟网络中传输私网流量&#xff0c;在不改变网络现状的情况下实现安全、可靠的连接。 专用&#xff1a;VPN网络是专门供VPN用户使用的网络&#xff0c;对于VPN用户&#xf…

geecg-uniapp 同源策略 数据请求 获取后台数据 进行页面渲染 ui库安装 冲突解决(3)

一&#xff0c;同源策略 &#xff08;1&#xff09;首先找到env 要是没有env 需要创建一个替换成后端接口 &#xff08;2&#xff09;因为他封装了 先找到 http 请求位置一级一级找 然后进行接口修改 &#xff08;3&#xff09;appUpdata 修改接口 运行即可 &#x…

【postgresql】

看到group by 1&#xff0c;2 和 order by 1&#xff0c; 2。看不懂&#xff0c;google&#xff0c;搜到了Stack Overflow 上有回答 What does SQL clause “GROUP BY 1” mean? 大概意思就是&#xff0c;group by&#xff0c; order by 后面跟数字&#xff0c;指的是 selec…

dockerfile 搭建lnmp+wordpress,docker-compose搭建lnmp+wordpress

目录 dockerfile 搭建lnmpwordpress 部署nginx&#xff08;容器IP 为 172.18.0.10&#xff09; 部署mysql&#xff08;容器IP 为 172.18.0.20&#xff09; 部署php&#xff08;容器IP 为 172.18.0.30&#xff09; docker-compose搭建lnmpwordpress dockerfile 搭建lnmpword…

STM32单片机采用环形缓冲区实现串口中断数据接收管理

一、前言 在嵌入式系统开发中&#xff0c;与上位机进行串口通信是非常常见的场景。上位机可以通过串口发送指令或者数据给嵌入式设备&#xff0c;而嵌入式设备需要可靠地接收并解析这些数据&#xff0c;以执行相应的操作。然而&#xff0c;在串口通信过程中&#xff0c;上位机…

Error: error:0308010C:digital envelope routines::unsupported

这个错误通常发生在使用 Node.js 中的 TLS/SSL 模块时。它表示在尝试建立 TLS 连接时&#xff0c;无法识别或不支持远程服务器所使用的加密协议。 可能的原因包括以下几点&#xff1a; 远程服务器使用了不安全的加密算法或协议&#xff0c;而最新版本的 OpenSSL 已经将其移除…

如何实现前端路由保护?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

OpenCV实现图像傅里叶变换

傅里叶变换 dftcv.dft(img_float32,flagscv.DFT_COMPLEX_OUTPUT): flags:标志位&#xff0c;指定变换类型&#xff0c;cv.DFT_COMPLEX_OUTPUT会返回复数结果。 傅立叶变换&#xff0c;将输入的图像从空间域转换到频率域。 返回结果: 此函数返回一个复杂数值数组&#xff0c…

初学者必看,前端 Debugger 调试学习

1.文章简介&#xff1a; 报错和Bug&#xff0c;是贯穿程序员整个编程生涯中&#xff0c;无法回避的问题。而调试&#xff0c;就是帮助程序员定位问题、解决问题的重要手段&#xff0c;因此调试是每个程序员必备技能。 调试本身可分为两个过程: 定位问题 和 解决问题&#xff0…

4Spring及Spring系列-基本

8、Spring/Spring MVC Spring常见面试题55道&#xff08;附答案2023最新版&#xff09;_spring面试题-CSDN博客Spring是一个开源的Java企业级开发框架&#xff0c;由Rod Johnson于2003年创建。它提供了一套全面的编程和配置模型&#xff0c;用于构建现代化的基于Java的企业应用…

基于 SpringBoot+Hikvision SDK 远程查看配置海康网络摄像头配置

写在前面 工作中遇到&#xff0c;简单整理理解不足小伙伴帮忙指正 对每个人而言&#xff0c;真正的职责只有一个&#xff1a;找到自我。然后在心中坚守其一生&#xff0c;全心全意&#xff0c;永不停息。所有其它的路都是不完整的&#xff0c;是人的逃避方式&#xff0c;是对大…

多输入多输出 | MATLAB实现CNN-BiGRU-Attention卷积神经网络-双向门控循环单元结合SE注意力机制的多输入多输出预测

多输入多输出 | MATLAB实现CNN-BiGRU-Attention卷积神经网络-双向门控循环单元结合SE注意力机制的多输入多输出预测 目录 多输入多输出 | MATLAB实现CNN-BiGRU-Attention卷积神经网络-双向门控循环单元结合SE注意力机制的多输入多输出预测预测效果基本介绍程序设计往期精彩参考…

HarmonyOS学习 -- ArkTS开发语言入门

文章目录 一、编程语言介绍二、TypeScript基础类型1. 布尔值2. 数字3. 字符串4. 数组5. 元组6. 枚举7. unknown8. void9. null 和 undefined10. 联合类型 三、TypeScript基础知识条件语句if语句switch语句 函数定义有名函数和匿名函数可选参数剩余参数箭头函数 类1. 类的定义2.…

低压配电系统中浪涌保护器的作用,安装位置和接线方法

低压配电系统是指在变压器低压侧或用户侧的电气装置&#xff0c;主要用于向用户提供安全、可靠和经济的电能。低压配电系统中常见的电气设备有低压配电柜、分支箱、开关箱、插座、照明等。这些设备都需要防止因外部或内部原因产生的过电压对其造成损坏或影响其正常工作。过电压…