python实现自动化报表功能(Oracle/plsql/Excel/多线程)


Posted in Python onDecember 02, 2019

日常会有很多固定报表需要手动更新,本文将利用python实现多线程运行oracle代码,并利用xlwings包和numpy包将结果写入到指定excel模版(不改变模版内容),并自动生成带日期命名的新excel。此外还添加了logging模块记录运行日志,以及利用try…except实现遇到错误自动重新运行。下面将介绍整个自动化的实现过程。

# -*- coding: utf-8 -*-
# Create time: 2019-10-16
# Update time: 2019-11-28
# Version: 1.0
# Version: 2.0 增加多线程/出错自动重新运行模块
# 导入模块
import cx_Oracle
import os
import pandas as pd
import pandas.io.sql as sql
import time
import openpyxl
import xlwings as xw
import logging 
import re
import threading
# 获取工作目录
sqlpath = os.getcwd() + '\\' # 获取当前文件夹目录,若不正确则使用后面的代码直接输入 sqlpath = 'E:\\'
# 设置运行日志
logging.basicConfig(format='%(asctime)s - %(pathname)s] - %(levelname)s: %(message)s', level=logging.INFO, filename=sqlpath+'log.txt')
# 获取系统日期(用于命名文件)
time_start=time.time()
date = time.strftime("%Y%m%d")
# 定义变量
name = '经营日报' # 模版名称
print('开始运行: %s' %name)
# sql代码文件名
sql1 = sqlpath + 'hangxian_ri.sql'
sql2 = sqlpath + 'hangxian_zhou.sql'
sql3 = sqlpath + 'hangxian_yue.sql'
# 定义空DataFrame(函数中要使用,必须要先定义)
result1 = pd.DataFrame()
result2 = pd.DataFrame()
result3 = pd.DataFrame()
# 定义可以读取运行sql的函数
def read_run_write1(sql_name):
  global result1 # 调用全局变量result1,使用global才能对全局变量进行修改
  print('正在运行代码: %s' %sql_name)
  with open(sql_name,encoding='utf-8-sig',mode='r') as f: # 读取oracle代码,中文编码utf-8-sig,
    sql_list = f.read()
    sql_list = re.sub(r'--.*', '', sql_list) # 去除注释
  connection = cx_Oracle.connect('账号/密码@IP地址/数据库名称')
  code = sql_list.replace('\n', ' ').replace(';','') # 将换行符转为空格,去除分号
  for i in range(5): # 运行oracle代码,若运行失败则10秒自动重新运行
    try:
      result1 = sql.read_sql(code, connection) # 利用pd包的read_sql函数运行代码,返回DataFrame类型的结果
      break # 代码运行成功则跳出循环
    except:
      print('代码%s运行出错,正在重新运行第%d次' %(sql_name,(i+1)))
      time.sleep(10) # 代码运行失败则10秒后再重新运行
  print('代码运行完成: %s' %sql_name)

def read_run_write2(sql_name):
  global result2
  print('正在运行代码: %s' %sql_name)
  with open(sql_name,encoding='utf-8-sig',mode='r') as f:
    sql_list = f.read()
    sql_list = re.sub(r'--.*', '', sql_list) # 去除注释
  connection = cx_Oracle.connect('账号/密码@IP地址/数据库名称')
  code = sql_list.replace('\n', ' ').replace(';','') # 将换行符转为空格,去除分号
  for i in range(5):
    try:
      result2 = sql.read_sql(code, connection)
      break
    except:
      print('代码%s运行出错,正在重新运行第%d次' %(sql_name,(i+1)))
      time.sleep(10)
  print('代码运行完成: %s' % sql_name)

def read_run_write3(sql_name):
  global result3
  print('正在运行代码: %s' %sql_name)
  with open(sql_name,encoding='utf-8-sig',mode='r') as f:
    sql_list = f.read()
    sql_list = re.sub(r'--.*', '', sql_list) # 去除注释
  connection = cx_Oracle.connect('账号/密码@IP地址/数据库名称')
  code = sql_list.replace('\n', ' ').replace(';','') # 将换行符转为空格,去除分号
  for i in range(5): 
    try:
      result3 = sql.read_sql(code, connection)
      break
    except:
      print('代码%s运行出错,正在重新运行第%d次' %(sql_name,(i+1)))
      time.sleep(10)
  print('代码运行完成: %s' % sql_name)

# 多线程运行sql代码
if __name__ == '__main__':
  t1 = threading.Thread(target=read_run_write1, args=(sql1,)) # 调用函数,并传递参数sql1,注意当只有一个参数时,参数后面需要有逗号
  t2 = threading.Thread(target=read_run_write2, args=(sql2,))
  t3 = threading.Thread(target=read_run_write3, args=(sql3,))
  t1.start() # 开始运行
  t2.start()
  t3.start()
  t1.join() # 加入线程,若无join()则运行完一个主线程后则会自动跳出,运行下面的代码,而不会等待其他线程运行完成
  t2.join()
  t3.join()

# 写入数据
print('正在写入数据')
app = xw.App(visible=False,add_book=False) # visible=False后台打开Excel程序
wb = app.books.open(sqlpath+name+'.xlsx') # 打开给定只保留标题和公式的空模版
wb.sheets['单日'].range('A4').options(expand='table').value=result1[:].values # result[:].values写法可以去掉索引和标题,将result1写入到表格'单日',从A4单元格开始
wb.sheets['滚动一周'].range('A4').options(expand='table').value=result2[:].values
wb.sheets['月累计'].range('A4').options(expand='table').value=result3[:].values
filename = sqlpath+name+date+'.xlsx' # 命名新生成的excel
wb.save(filename) # 另存为新Excel,不改变模版
wb.close() # 关闭工作簿
print(filename+'已自动生成') 
time_end=time.time() 
print("程序运行时间:%.2f s" % (time_end-time_start)) 
logging.info("程序运行时间:%.2f s" % (time_end-time_start)) # 记录程序运行时间到运行日志log.txt中

python自动化中的一些难点

  • 多线程无法同时对excel进行写入操作,如果直接在函数中运行完成后直接写入,并利用多线程运行,会报错com模块冲突
  • 为了解决函数不能直接生成结果变量的问题, 应先定义空DataFrame,并在函数中global声明为调用全局变量才能达到运行完函数生成变量的效果(可能还有其他更好方法)

运行结果

python实现自动化报表功能(Oracle/plsql/Excel/多线程)

总结

以上所述是小编给大家介绍的python实现自动化报表(Oracle/plsql/Excel/多线程),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Python 相关文章推荐
老生常谈进程线程协程那些事儿
Jul 24 Python
Windows下的Jupyter Notebook 安装与自定义启动(图文详解)
Feb 21 Python
Python基于递归实现电话号码映射功能示例
Apr 13 Python
python实现读Excel写入.txt的方法
Apr 29 Python
Python设置在shell脚本中自动补全功能的方法
Jun 25 Python
python使用ddt过程中遇到的问题及解决方案【推荐】
Oct 29 Python
使用CodeMirror实现Python3在线编辑器的示例代码
Jan 14 Python
pandas修改DataFrame列名的实现方法
Feb 22 Python
Tensorflow模型实现预测或识别单张图片
Jul 19 Python
Python描述符descriptor使用原理解析
Mar 21 Python
Python闭包及装饰器运行原理解析
Jun 17 Python
Python 解析简单的XML数据
Jul 24 Python
Python中类似于jquery的pyquery库用法分析
Dec 02 #Python
python 检查数据中是否有缺失值,删除缺失值的方式
Dec 02 #Python
python实现两个字典合并,两个list合并
Dec 02 #Python
Python:合并两个numpy矩阵的实现
Dec 02 #Python
DataFrame.to_excel多次写入不同Sheet的实例
Dec 02 #Python
python实现数据清洗(缺失值与异常值处理)
Dec 02 #Python
python字符串反转的四种方法详解
Dec 02 #Python
You might like
PHP fgetcsv 定义和用法(附windows与linux下兼容问题)
2012/05/29 PHP
Laravel5.5 视图 - 创建视图和数据传递示例
2019/10/21 PHP
laravel框架中视图的基本使用方法分析
2019/11/23 PHP
php设计模式之职责链模式实例分析【星际争霸游戏案例】
2020/03/27 PHP
JQuery中的ready函数冲突的解决方法
2010/05/17 Javascript
JQuery中each()的使用方法说明
2010/08/19 Javascript
基于jquery实现后台左侧菜单点击上下滑动显示
2013/04/11 Javascript
JS获取键盘上任意按键的值(实例代码)
2013/11/12 Javascript
javascript简单实现表格行间隔显示颜色并高亮显示
2013/11/29 Javascript
js获取某元素的class里面的css属性值代码
2014/01/16 Javascript
jquery选择器需要注意的问题
2014/11/26 Javascript
七个不允许错过的jQuery小技巧
2015/12/21 Javascript
JS插件overlib用法实例详解
2015/12/26 Javascript
详解nodejs爬虫程序解决gbk等中文编码问题
2017/04/06 NodeJs
JS传播事件、取消事件默认行为、阻止事件传播详解
2017/08/14 Javascript
VUE中使用MUI方法
2019/02/12 Javascript
微信小程序搭建自己的Https服务器
2019/05/02 Javascript
vue element el-transfer增加拖拽功能
2021/01/15 Vue.js
[40:13]Ti4 冒泡赛第二天 iG vs NEWBEE 2
2014/07/15 DOTA
[01:30]2016国际邀请赛中国区预选赛神秘商店火爆开启
2016/06/26 DOTA
[48:22]VGJ.S vs VG 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
[05:09]DOTA2-DPC中国联赛2月22日Recap集锦
2021/03/11 DOTA
Python实现判断给定列表是否有重复元素的方法
2018/04/11 Python
Python 变量类型详解
2018/10/10 Python
详解python 中in 的 用法
2019/12/12 Python
Python PyQt5运行程序把输出信息展示到GUI图形界面上
2020/04/27 Python
纽约的奢华内衣店:Journelle
2016/07/29 全球购物
尤妮佳moony海外旗舰店:日本殿堂级纸尿裤品牌
2018/02/23 全球购物
行政助理工作职责范本
2014/03/04 职场文书
幼儿园春季开学寄语
2014/04/03 职场文书
平面设计师岗位职责
2014/09/18 职场文书
2015年学习部工作总结范文
2015/03/31 职场文书
小学科学课教学反思
2016/02/23 职场文书
《夹竹桃》教学反思
2016/02/23 职场文书
关于golang高并发的实现与注意事项说明
2021/05/08 Golang
Python中with上下文管理协议的作用及用法
2022/03/18 Python