主要是工作中需要使用java去调用python执行导出mongodb数据为excel表格的需求 所以在完成中遇到很多坑做的一个自我总结和记录
一.python代码部分
- python的代码部分主要封装了mongodb数据库的端口 用户密码校验 还有导出为excel表格的方法 并保存py文件的位置提供给java调用(本文是放在"D:\PycharmProjects\venv\Include\mongodb.py")
- 直接上代码(需要注意的是python中import的jar需要现在本地环境按照下载好):
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2019/12/2 0002 下午 4:03
# @Author : pcc
# @Site :
# @File : mongodb.py
# @Software: PyCharm
import sys
import csv
import datetime
import json
import openpyxl
import pandas as pd
import xlwt
from openpyxl import load_workbook
from pymongo import MongoClient
"""
user 用户名
pwd 密码
server 服务器ip
port 数据库端口号
db_name 数据库名
table_name 集合名
form_data 想要获取的字段列表
"""
# 导出为csv方法
def export(user, pwd, server, port, db_name, table_name, form_data, file, prame):
uri = 'mongodb://' + user + ':' + pwd + '@' + server + ':' + port + '/'
client = MongoClient(uri)
db = client[db_name][table_name]
# with open(f"{db_name}_{table_name}.csv", "w", newline='', encoding='gbk') as csvfilewrite:
with open(file, "w", newline='', encoding='gbk') as csvfilewrite:
write = csv.writer(csvfilewrite)
write.writerow(name_list)
allRecordRes = db.find(prame)
for record in allRecordRes:
recordValueLst = []
for field in form_data:
if field not in record:
recordValueLst.append("None")
else:
recordValueLst.append(record[field])
try:
write.writerow(recordValueLst)
except Exception as e:
print(f"write csv exception.e = {e}")
# 创建工作簿对象csv_to_xlsx
def csv_to_xlsx(db_name, table_name, csvfile, outfile):
# 创建工作簿对象
work_book = openpyxl.Workbook()
# 创建sheet
work_sheet = work_book.active
# 打开csv文件
csvfile = open(csvfile, encoding='gbk')
# 获取csv.reader
lines = csv.reader(csvfile)
# row
row = 1
# 写入从csv读取的内容 如使用了以上代码 这里行数要加一
for line in lines:
lin = 1
for i in line:
work_sheet.cell(row=row, column=lin).value = i
lin += 1
row += 1
# 关闭文件
csvfile.close()
# 保存工作表
work_book.save(outfile)
if __name__ == '__main__':
# 用户名
user = "*******"
# 密码
pwd = "******"
# 服务器ip
server = "127.0.0.1"
# 服务器端口号
port = "27017"
# 数据库名
db_name = "db_test"
# 集合名
table_name = "table_test"
# 想要获取字段的列表
form_data = [
'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l'
]
# 想要获取字段的列表中文注释
name_list = [
'1', '2', '3', '4', '5', '6', '7', '8',
'9', '10', '11', '12'
] # 表格第一行, 名称
# file = './doctor_singed.csv'
file = r'D:/python/XXXX.csv'
# outfile 是导出表格的地址路径
outfile = r'D:/python/ ' + datetime.datetime.now().strftime('%Y%m%d%H%M%S') + '.xlsx'
print("开始时间:"+datetime.datetime.now().strftime('%Y%m%d%H%M%S'))
# prame={"$and": [{"$or": [{"aa": "B77129110045489946DC88FBFC788E12"}]}]}
# prame={"\"$and\"": [{"\"$or\"": [{"\"aa\"": "\"B77129110045489946DC88FBFC788E12\""}]}]}
# sys.argv[1]获取传参的参数
print('sys.argv[1]:' + sys.argv[1])
data = sys.argv[1]
print('data:' + data)
# 查看data的类型
print(type(data))
# 将data(sys.argv[1])获取传参的参数转为json对象
prame = json.loads(data)
# 数据库数据导出为csv格式
export(user, pwd, server, port, db_name, table_name, form_data, file, prame)
# csv格式转换成excel格式
csv_to_xlsx(db_name, table_name, file, outfile)
print("结束时间:"+datetime.datetime.now().strftime('%Y%m%d%H%M%S'))
二.java代码部分
- 目前java调用python的方法有几种 我推荐使用(不需要依赖第三方jar直接代码就可以了):
Process process = Runtime.getRuntime().exec(arguments);
- 因为我们导出数据还要导出条件查询所以条件肯定实在前面入参需要封装传参:
BasicDBObject searchCond = new BasicDBObject();
- 完整java代码如下:
package com.XXX.XXX.XXX.XXX.XXX;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.QueryOperators;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class HelloPython {
public static void main(String[] args) {
//mongodb参数封装 请一定注意需要用转义符去转义双引号"" 不然在传参到python脚本的时候参数的双引号""会丢失(重点注意)
BasicDBList condList1 = new BasicDBList();
BasicDBObject searchTeamNo = new BasicDBObject();
BasicDBObject cond = new BasicDBObject();
cond.put("\"aa\"","\"B77129110045489946DC88FBFC788E12\"");
condList1.add(cond);
searchTeamNo.put("\""+QueryOperators.OR+"\"", condList1);
BasicDBList condList = new BasicDBList();
condList.add(searchTeamNo);
BasicDBObject searchCond = new BasicDBObject();
searchCond.put("\""+QueryOperators.AND+"\"", condList);
//arguments是参数封装
// 数组第一位"python"是代表执行python脚本
// 数组第二位是"D:\\PycharmProjects\\venv\\Include\\mongodb.py" 代表执行python脚本的文件或者系统的路径
// 数组第三位是传递的参数(本文传的是mongodb参数封装)
String[] arguments = new String[] {"python", "D:\\PycharmProjects\\venv\\Include\\mongodb.py", searchCond.toString()};
System.out.println(searchCond.toString());
try {
//java执行调用python的运行方法 传参arguments
Process process = Runtime.getRuntime().exec(arguments);
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream(),"gbk"));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
in.close();
//java代码中的process.waitFor()返回值为0表示我们调用python脚本成功,
//返回值为1表示调用python脚本失败,这和我们通常意义上见到的0与1定义正好相反
int re = process.waitFor();
System.out.println(re);
process.destroy();
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 执行java mian()方法
- 按照最后返回值为1表示调用python脚本失败,0代表用python脚本成功 并保存