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 相关文章推荐
Python 异常处理实例详解
Mar 12 Python
Python字符串格式化输出方法分析
Apr 13 Python
Python爬取附近餐馆信息代码示例
Dec 09 Python
Python用csv写入文件_消除空余行的方法
Jul 06 Python
python 求一个列表中所有元素的乘积实例
Jun 11 Python
python实现各种插值法(数值分析)
Jul 30 Python
Python数据分析模块pandas用法详解
Sep 04 Python
python集合的创建、添加及删除操作示例
Oct 08 Python
基于python tkinter的点名小程序功能的实例代码
Aug 22 Python
Python confluent kafka客户端配置kerberos认证流程详解
Oct 12 Python
python OpenCV学习笔记
Mar 31 Python
Python Pandas数据分析之iloc和loc的用法详解
Nov 11 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
composer.lock文件的作用
2016/02/03 PHP
Yii2中OAuth扩展及QQ互联登录实现方法
2016/05/16 PHP
PDO::getAttribute讲解
2019/01/28 PHP
PHP单例模式数据库连接类与页面静态化实现方法
2019/03/20 PHP
php文件后缀不强制为.php的实操方法
2019/09/18 PHP
PHP切割整数工具类似微信红包金额分配的思路详解
2019/09/18 PHP
laravel与thinkphp之间的区别与优缺点
2021/03/02 PHP
防止页面被iframe(兼容IE,Firefox火狐)
2010/07/04 Javascript
js动态创建表格,删除行列的小例子
2013/07/20 Javascript
对new functionName()定义一个函数的理解
2014/05/22 Javascript
js使用递归解析xml
2014/12/12 Javascript
JavaScript中的对象的extensible属性介绍
2014/12/30 Javascript
JavaScript数据操作_浅谈原始值和引用值的操作本质
2016/08/23 Javascript
jquery层级选择器的实现(匹配后代元素div)
2016/09/05 Javascript
利用bootstrapValidator验证UEditor
2016/09/14 Javascript
bootstrap 模态框(modal)实现水平垂直居中显示
2017/01/23 Javascript
Bootstrap modal 多弹窗之叠加关闭阴影遮罩问题的解决方法
2017/02/27 Javascript
Vue中添加过渡效果的方法
2017/03/16 Javascript
深入理解Vue 的条件渲染和列表渲染
2017/09/01 Javascript
vue脚手架搭建项目的兼容性配置详解
2018/07/17 Javascript
fastadmin中调用js的方法
2019/05/14 Javascript
关于你不想知道的所有Python3 unicode特性
2014/11/28 Python
介绍Python中的一些高级编程技巧
2015/04/02 Python
python生成器,可迭代对象,迭代器区别和联系
2018/02/04 Python
python网络爬虫学习笔记(1)
2018/04/09 Python
Python中Numpy mat的使用详解
2019/05/24 Python
PYcharm 激活方法(推荐)
2020/03/23 Python
英国乐购杂货:Tesco Groceries
2018/11/29 全球购物
Helly Hansen工作服美国官方网上商店:为最恶劣的环境
2019/09/04 全球购物
英国领先的高级美容和在线皮肤诊所:Face the Future
2020/06/17 全球购物
建筑专业毕业生推荐信
2013/11/21 职场文书
建筑安全员岗位职责
2014/03/13 职场文书
驾驶员培训方案
2014/05/01 职场文书
防邪知识进家庭活动方案
2014/08/26 职场文书
2015年端午节活动方案
2015/05/05 职场文书
Nginx反爬虫策略,防止UA抓取网站
2021/03/31 Servers