一、目的
动手写这个小功能主要出于简化工作量,提高工作效率。由于支付行业,每一笔资金的入款和出款都非常重要,所以测试过程中涉及到真实交易都需要记录,并发送给清算部门,方便资金的核对。如果某天测试数据量很大,那么几乎一个上午都用在手动整理交易记录表格上,则其他的测试计划可能被耽误,由此想到用python写一个小工具,只要输入商户编号、查询的开始时间和结束时间,则自动产生成一份对应商户某段时间内的入账记录excel。
二、环境
- win7 64位系统
- python 3.5 64位
- oracle client 11gR2 64位
- cx_Oracle-5.3-11g.win-amd64-py3.5-2.exe (md5)
三、思路
- 连接oracle数据,通过查询数据库获取所需要的数据信息,保存到列表listA里
- 先转化处理查询的数据listA,再写入到excel。
- 编辑命令bat文件中的三个参数,通过双击bat文件,自动执行脚本生产入账记录表格
四、过程中遇到的坑以及解决办法
- 环境配置的坑
- import cx_Oracle成功后,执行连接oracle数据库脚本,遇到报错:cx_Oracle.InterfaceError:Unable to acquire Oracle envirment handle
解决办法:原先我的32位oracle版本不合适,开始想试过从其他同事的64位oracle安装目录下拷贝oci.dll、ocijdbc11.dll和oraociell.dll导入到python安装目录site-packages下,这种办法是不可行。正确的办法只有到oracle官网重新下载安装合适的oracle client版本。 - oracle的环境变量未配置
解决办法:使用cx_Oracle模块需要配置python和oracle的环境变量。oracle需要配置2个值:环境变量增加ORACLE_HOME变量名,变量值指向oracle安装目录中oci.dll文件所在的路径;环境变量path后面加入oracle安装目录中oci.dll文件所在的路径。
- 思路的坑
1.查询数据处理和写excel逻辑的先后顺序
正确思路:逻辑上应该先处理转化好查询的数据,再开始写入excel。由于入账记录表的数据模板都是公司制定好的,而数据库里获取的listA数据并不是完全符合,所以在写表之前,先处理listA数据,转化好数据。比如某些字段是数字,但是字段值代表的含义,非开发和测试人员根本不明白,所以不同的数字需要映射成不同内容;再比如我们的数据库表设计上消费和撤销都是同一笔流水数据,撤销数据是在消费数据上进行处理的,不会产生新的流水号,而入账记录表则需要分别记录消费和撤销两条数据。若是先写excel的话,再进行数据处理和插入数据,逻辑会更复杂,而且会更容易出现问题。 - cx_Oracle中英文乱码的坑
1.在使用cx_Oracle读取数据库,查询的中文信息出现?号
解决办法:脚本头部加入如下2行代码 - argv理解不够透彻
1.使用argv传参,运行方法不正确(argv是获取命令行参数列表)
遇到报错:print(sys.argv[1]) IndexError:list index out of range - 解决办法:应该在pycharmProjects工具下方的Terminal里执行:python xx.py aa 命令。sys.argv第一个参数是文件名,第二个参数开始是命令行输入的参数,以空格隔开。
五、附上完整代码
import cx_Oracle,xlwt,time,sys
import os# 解决查询结果中文乱码的问题,设置oracle客户端的字符编码为utf-8
os.environ[‘NLS_LANG’] = ‘SIMPLIFIED CHINESE_CHINA.UTF8’print(sys.argv[0])#传入脚本路径
print(sys.argv[1])#传入商户编号
print(sys.argv[2])#传入查询开始时间,格式如: 2017-03-16T00:00:00Z
print(sys.argv[3])#传入查询结束时间,格式如: 2017-03-16T00:00:00ZEnvironment=’测试’ #环境
title = [ #excel字段内容
‘创建时间’,
‘环境’,
‘转入账号’,
‘交易渠道’,
‘机构订单号’,
‘交易金额’,
‘手续费’,
‘支付银行’,
‘支付状态’,
‘签购单打印状态’,
‘交易类型’,
‘备注’
]
chan ={
0: ‘x1渠道’,
1: ‘x2渠道’,
2: ‘x3渠道’,
3: ‘x4渠道’}
cur_status = {
1: ‘支付成功’,
5: ‘撤销中’,
6: ‘撤销成功’,
9: ‘撤销失败’
}
t = 0
types = [] #存放交易类型
prit = [] #存放签购单打印状态
resfull =[]#新列表,增加了撤销数据的原交易数据def get_oracle_data(agent_num,sstime,eetime):#获取查询结果函数
# 转换成时间数组
rtime = time.strptime(sstime, “%Y-%m-%dT%H:%M:%SZ”)
# 转换成时间戳
stime = time.mktime(rtime)
# 转换成时间数组
retime = time.strptime(eetime,”%Y-%m-%dT%H:%M:%SZ”)
# 转换成时间戳
etime = time.mktime(retime)
#查询的SQL语句
oracle_sql = ”’
….查询SQL语句省略….
”’%(agent_num,stime,etime)
host = “192.168.xxx.xx”
port = “1521”
sid = “xxxx”
user = “xxxx”
pwd = “xxxx”
dsn = cx_Oracle.makedsn(host, port, sid)
conn = cx_Oracle.connect(user, pwd, dsn)
cursor = cx_Oracle.Cursor(conn)
cursor.execute(oracle_sql)
res=cursor.fetchall()
cursor.close()
conn.close()
return resresults = get_oracle_data(sys.argv[1],sys.argv[2],sys.argv[3])#调用函数,产生查询结果数据
#写excel
wbk = xlwt.Workbook()
sheet = wbk.add_sheet(‘sheet1’)
for i in range(len(title)):#写表头
sheet.write(0,i,title[i])#处理转化查询的数据:映射部分字段数据,同时撤销数据前插入原消费交易数据,重新生成多个新的数组
for i in range(len(results)):
if results[i][5] == 1:
resfull.append(results[i])
prit.append(‘打印成功’)
types.append(‘消费’)
elif results[i][5] == 6:
resfull.append((results[i][0],results[i][1],results[i][2],results[i][3],results[i][4],1,results[i][6],results[i][7]))
resfull.append(results[i])
prit.append(‘打印成功’)
prit.append(‘打印成功’)
types.append(‘消费’)
types.append(‘消费撤销’)
else:
resfull.append((results[i][0], results[i][1], results[i][2], results[i][3], results[i][4], 1, results[i][6],results[i][7]))
resfull.append(results[i])
prit.append(‘打印成功’)
prit.append(‘未打印’)
types.append(‘消费’)
types.append(‘消费撤销’)for i in range(len(resfull)):#循环新的列表,写入Excel
if resfull[i][5] ==1:
sheet.write(i + 1, title.index(‘机构订单号’), resfull[i][3])
sheet.write(i + 1, title.index(‘交易金额’), resfull[i][7])
else:
sheet.write(i + 1, title.index(‘机构订单号’), resfull[i][8])
sheet.write(i + 1, title.index(‘交易金额’), -resfull[i][7])
time_local = time.localtime(resfull[i][0])
create_time = time.strftime(“%Y-%m-%d %H:%M:%S”, time_local)
sheet.write(i + 1, title.index(‘创建时间’), create_time)
sheet.write(i + 1, title.index('环境'), Environment)
sheet.write(i + 1, title.index('转入账号'), resfull[i][1])
channel = chan[(resfull[i][2])]
sheet.write(i + 1, title.index('交易渠道'), channel)
bank_name = (resfull[i][4]).split('::')[0]
sheet.write(i + 1,title.index('支付银行'),bank_name)
sheet.write(i + 1, title.index('支付状态'),cur_status[(resfull[i][5])])
sheet.write(i + 1, title.index('备注'), resfull[i][6])
sheet.write(i + 1, title.index('交易类型'), types[i])
sheet.write(i + 1, title.index('签购单打印状态'), prit[i])
wbk.save(‘xx入款对账记录-autoxxx.xls’)
六、总结
- 过程中总会遇到各种问题,尝试在网上找解决办法,实在不行再请教其他人。
- 先敲,一定要敲代码,自己一步步来,整个功能也就写出来了。
- 上面的代码虽然功能是简单实现了,但是很多代码都存在重复,后面会慢慢优化。而且这个代码是一股脑的写下来的,没有什么结构化,异常处理逻辑也都忽略了。
- 针对编辑bat文件达到参数的输入不是很方便,后面一篇准备尝试调用tkinter模块,实现在图形界面上输入需要的参数,启动自动生成入账记录脚本。
- 最后生成的表格,如下图所示: