python连接数据库自动发邮件
python连接数据库实现自动发邮件
1.运行环境
redhat6 + python3.6 + crontab + Oracle客户端
2.用到的模块

3.操作步骤
(1)安装python3.6参考步骤https://www.cnblogs.com/zhur/p/12044171.html
(2)安装python模块,pip安装
4.安装Oracle客户端https://oracle.github.io/odpi/doc/installation.html#linux
5.配置环境变量 ~/.bash_profile
(1)LD_LIBRARY_PATH=[oracle客户端安装目录]:$LD_LIBRARY_PATH
(2)export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK(数据库中的)
6.编写配置文件和执行脚本
(1)配置文件:
##数据库相关参数:主机 、数据库用户、数据库密码、数据库sid、数据库字符集nls_lan
ora_host = '192.168.168.168'
ora_user = '**********'
ora_pwd = '**********'
ora_sid = '****'
##nls_lan = 'AMERICAN_AMERICA.ZHS16GBK'
##数据库共享库目录
##lib_path = '/opt/oracle/instantclient_11_2'
##执行脚本(py,sql)目录
exe_path = '/root/python/prod/cstest/bin'
##数据库导出sql语句文件,多个文件用逗号隔开;如果sql文件在执行脚本目录下,可以使用相对路径,否则使用绝对路径;
##注意:标点符号都是英文的,sql文件中的时间变量必须是 &date 或 &yyyymmdd
sql_files = '/root/python/prod/cstest/bin/测试.sql'
## sql语句中的导数日期 yesterday :表示昨天 ,目前只支持这一种情况,以后可以酌情增加其它日期
exp_date = 'yesterday'
##导出excel目录
excel_path = "/root/python/prod/cstest/data"
##导出excel文件sheet名,sheet名称与上面参数sql_files中的每个sql文件中sql条数一一对应,如果没有设置对应名称,则sheet名称默认
excel_sheet_names = [['测试']]
##导出exel文件是否压缩 1:压缩 0:不压缩 删除此参数
##is_zip = 1
##压缩后文件名前缀 ,压缩文件名=前缀+导数日期
zipfile_name = '测试'
##是否发送邮件 1: 发送 0:不发送
is_mail = 1
##邮箱发送服务器
mail_server = 'xxxxxxxxx.@com'
##邮箱发送服务器端口
mail_port = '**'
##发送邮件
mail_from = 'xxxxxxxx@qq.com'
##发送邮件密码
mail_pass = '********'
##接收邮件
mail_to = 'xxxxxxxx@qq.com'
#抄送邮件
mail_cc = 'xxxxxxxxx@qq.com'
##邮件标题
mail_subject = '测试'
##邮件内容
mail_body = """
<p>您好:</p>
<p> 数据已提取,详见附件,请查收; </p>
<p></p>
<p></p>
<p>-------------------------------------------------------------------------------------</p>
<p> 可视化运维:朱瑞
<p> 热线电话:18834195657 </p>
<p> 运维邮箱:xxxxxxxxx@qq.com</p>
"""
(2)执行脚本
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import cx_Oracle as cx
from openpyxl import Workbook
import datetime
import os
import zipfile
from config_ora2excel import *
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email import encoders
from email.header import Header
from email.mime.base import MIMEBase
#os.environ['LD_LIBRARY_PATH'] = lib_path
#os.environ['NLS_LANG'] = nls_lan
#os.environ.setdefault("LD_LIBRARY_PATH", lib_path)
#os.environ.setdefault("NLS_LANG", nls_lan)
def get_yesterday():
today = datetime.date.today()
oneday = datetime.timedelta(days=1)
yesterday = today - oneday
return yesterday
def get_data_date():
# 获取数据日期
##data_date = input('请输入数据日期,格式yyyymmdd,默认为昨天:')
data_date = exp_date
if data_date.strip().lower() == 'yesterday':
yesterday = get_yesterday()
data_date = yesterday.strftime("%Y%m%d")
##print(data_date)
return data_date
def get_weeks():
#获取周次
data_date = get_data_date()
y = int(data_date[:4])
m = int(data_date[4:6])
d = int(data_date[6:])
weeks = datetime.date(y,m,d).isocalendar()[1]
return weeks
def ora_to_excel(data_date):
try:
ret = 0
#print(os.environ['LD_LIBRARY_PATH'])
#print(os.environ['NLS_LANG'])
# 连接数据库
# connect = cx.connect(user+'/'+pwd+'@'+host+'/'+sid)
connect = cx.connect('{}/{}@{}/{}'.format(ora_user, ora_pwd, ora_host, ora_sid))
print('连接数据库成功!!')
# 获取数据日期
data_date = data_date
print(data_date)
##切换到脚本执行目录
os.chdir(exe_path)
# 获取sql执行并导出到excel,可能是多条sql,需要分别执行
fi = 0
for f_sql in sql_files.split(','):
start = datetime.datetime.now()
##print(type(f_sql))
cursor = connect.cursor()
print(f_sql)
with open(f_sql, 'r', encoding='utf-8') as f:
sqls = f.read()
j = 0
wb = Workbook()
for sql in sqls.split(';'):
sql = sql.strip()
if not sql:
break
##替换变量 sql中的变量必须是 &date 或 &yyyymmdd
# sql = sql.lower()
sql = sql.replace('&date', data_date)
sql = sql.replace('&yyyymmdd', data_date)
##sql = sql.decode('utf-8')
print('-----------------------------------------开始执行sql:\n', sql)
cursor.execute(sql)
print('-----------------------------------------执行sql成功\n')
print('-----------------------------------------开始导出excel\n')
sht = wb.create_sheet(title='Mysheet'+str(j),index=j)
## 如果变量设置了sheet名称,则修改
if len(excel_sheet_names) >= fi + 1:
if len(excel_sheet_names[fi]) >= j + 1 and excel_sheet_names[fi][j].strip():
sht.title = excel_sheet_names[fi][j]
print(sht.title)
# 处理表头
i = 1
for col in cursor.description:
sht.cell(1, i).value = col[0]
i += 1
##print('11')
# 写数据
##offset = 2
while True:
results = cursor.fetchmany(10000)
if not results:
break
resLen = len(results)
for res in results:
sht.append(res)
##在开头插入一列
###print('1111')
sht.insert_cols(1)
###print('22')
###print(sht.max_row)
# 给第一列写入行标
for k in range(2, sht.max_row+1):
sht.cell(k,1).value = k - 1
# 获取导出文件目录及文件名
exl_file = f_sql.split(os.sep)[-1].split('.')[0] + '_' + data_date + '.xlsx'
if excel_path.strip():
exl_file = excel_path + os.sep + exl_file
print(exl_file)
j += 1
wb.save(exl_file)
##wb.close()
cursor.close()
print('-----------------------------------------导出excel成功!\n')
print('导出excel 花费时间:', datetime.datetime.now() - start, '\n\n')
fi += 1
ret = 1
except Exception as e:
print('Error:', e)
##raise e
finally:
connect.close()
return ret
def get_zip_file(input_path, wd, results):
"""
在目录下查找包含关键字的文件
input_path: 目录
wd: 关键字
results:查找结果列表
"""
try:
files = os.listdir(input_path)
for filename in files:
fp = os.path.join(input_path, filename)
if os.path.isfile(fp) and wd in filename:
# 使用相对路径
results.append('.' + os.sep + filename)
except Exception as e:
print(e)
raise e
def zip_files(input_path, output_zip_name, data_date):
"""
压缩文件
input_path:目录
output_zip_name:zip文件名
data_date :数据日期
"""
try:
ret = None
start = datetime.datetime.now()
filelists = []
wd = data_date + '.xlsx'
get_zip_file(input_path, wd, filelists)
if len(filelists) > 0:
print('-----------------------------------------开始压缩文件')
f = zipfile.ZipFile(input_path + os.sep + output_zip_name, 'w', zipfile.ZIP_DEFLATED)
# 切换到打包目录
os.chdir(input_path)
for file in filelists:
f.write(file)
print(input_path + os.sep + output_zip_name)
print('-----------------------------------------压缩文件完成')
print('压缩文件 花费时间:', datetime.datetime.now() - start, '\n\n')
f.close()
print('压缩文件名:',input_path + os.sep + output_zip_name)
ret = output_zip_name
return ret
except Exception as e:
print('Error:', e)
raise e
finally:
return ret
def send_mail(zipfile):
# 构造一个MIMEMultipart对象代表邮件本身
msg = MIMEMultipart()
msg['From'] = mail_from
msg['To'] = mail_to
msg['Cc'] = mail_cc
weeks = str(get_weeks())
mail_sub = mail_subject.replace('{weeks}',weeks)
msg['Subject'] = Header(mail_sub,'utf-8').encode()
msg.attach(MIMEText(mail_body,'html','utf-8'))
# 切换到zip文件目录
os.chdir(excel_path)
#二进制模式读取zip文件
with open(zipfile,'rb') as f:
zipf = zipfile.split('.')[0]
# 设置附件的MIME和文件名,这里是zip类型:
mime = MIMEBase('zip', 'zip', filename=zipfile)
# 加上必要的头信息:
#mime.add_header('Content-Disposition', 'attachment', file_name=Header(zipfile,'utf-8').encode())
#mime.add_header('Content-Disposition', 'attachment', filename=('gbk', '', zipfile))
#mime.add_header('Content-Disposition', 'attachment', filename=('utf-8', '', zipfile)) ##这种方式发送,邮件客户端收到邮件,中文附件名还是可能有乱码
mime.add_header('Content-Disposition', 'attachment', filename= Header(zipfile,'gbk').encode() ) ## ##中文附件名称outlook,网页,foxmail均显示正常
#mime.add_header('Content-ID', '<0>')
#mime.add_header('X-Attachment-Id', '0')
# 把附件的内容读进来:
mime.set_payload(f.read())
# 用Base64编码
encoders.encode_base64(mime)
#添加到MIMEMultipart
msg.attach(mime)
try:
print('-----------------------------------------发送邮件开始')
s = smtplib.SMTP()
s.connect(mail_server,mail_port)
s.login(mail_from,mail_pass)
##sendmail的第2个参数邮件地址是个list,所以将字符串用split转为list
s.sendmail(mail_from,mail_to.split(',')+mail_cc.split(','),msg.as_string())
s.quit()
print('-----------------------------------------发送邮件结束')
except smtplip.SMTPException as e:
print('发送失败:',e)
return
def main():
try:
print('--Program begin',datetime.datetime.now(),'--------------------------------------')
print(os.environ['LD_LIBRARY_PATH'])
print(os.environ['NLS_LANG'])
data_date = get_data_date()
oret = ora_to_excel(data_date)
##oret = 1
weeks = str(get_weeks())
zfile_name = zipfile_name.replace('{weeks}',weeks)
output_zip_name = zfile_name + '_' + data_date + '.zip'
if oret == 1:
zfile = zip_files(excel_path, output_zip_name, data_date)
###zfile = output_zip_name
if zfile:
if is_mail == 1:
send_mail(zfile)
print('--Program End', datetime.datetime.now(), '--------------------------------------')
except Exception as e:
print(e)
## finally:
## end = input('请输入回车键结束!')
if __name__ == '__main__':
main()
7.测试看是否发送成功 用行脚本就ok
8.配置定时任crontab -e
9.遇到的问题
(1).执行脚本时无法调用模块,用pip 安装python模块报错

解决方法用国内镜像安装

(2)定时任务crontab 遇到的问题 配置好定时任务无法执行,查看没报错,执行完却没有发送成功,

解决方法,前面加入环境变量,先识别环境变量在执行py,

或将~/bash_profile 和 执行脚本写入shell脚本,设置定时任务执行shell脚本也可以

10.最后我的crontab 的配置

配置完成,成功发送,哈哈哈哈哈
python连接数据库自动发邮件的更多相关文章
- python实现自动发邮件
Python有两个内置库:smtplib和email,可以实现邮件功能,无需下载,直接import导入. smtplib库负责发送邮件 Email库负责构造邮件格式和内容 邮件发送需要遵守SMTP协议 ...
- python自动发邮件库yagmail
#### 一般发邮件方法 我以前在通过Python实现自动化邮件功能的时候是这样的: import smtplib from email.mime.text import MIMEText from ...
- python自动发邮件库yagmail(转)
一般发邮件方法 我以前在通过Python实现自动化邮件功能的时候是这样的: import smtplib from email.mime.text import MIMEText from email ...
- 【python】python 自动发邮件
一.一般发邮件的方法 Python对SMTP支持有smtplib和email两个模块,email负责构造邮件,smtplib负责发送邮件. 注意到构造MIMETEXT对象时,第一个参数就是邮件正文,第 ...
- Selenium 2自动化测试实战37(自动发邮件功能)
自动发邮件功能 例如,如果想在自动化脚本运行完成之后,邮箱就可以收到最新的测试报告结果.SMTP(Simple Mail Transfer Protocol)是简单邮件传输协议,它是一组用于由源地址到 ...
- PHP自动发邮件
自动发邮件 使用了这个类http://bbs.php100.com/read-htm-tid-121431.html 因他用的php版本较老,用到了函数ereg_replace() 和 ereg() ...
- java windows自动化-mail自动发邮件
本文旨在让测试人员了解如何发邮件 发邮件的话,最简单的事是直接手动发邮件,但是在自动化测试中,应做到让机器或者代码来自动发送邮件,笔者大概了解以下几种方法,总有一款口味适合你:1java代码来做下面即 ...
- jira6.3.6创建问题不自动发邮件通知的问题
装完jira6.3.6后,设置好邮件服务器,测试没有问题.但是创建问题不自动发邮件提示用户.折腾了大半天,请教了一位大神,终于搞定.步骤是: agile->系统->用户界面->用户缺 ...
- redmine创建新闻,自动发邮件给项目组所有成员
redmine创建新闻,自动发邮件给项目组所有成员: 1.添加用户至公共项目内 2.配置系统邮件推送配置 3.检查用户接受推送配置 3.使用管理员账户发布新闻(不能自己发送自己) 4.查看邮件接受邮件
随机推荐
- web开发中会话跟踪的方法有哪些
会话跟踪就是浏览器和服务器通信 1.cookie 2.session 3.隐藏input 4.url重写 5.ip地址
- Django聚合数据
背景: 有些时候,光靠数据库中已有字段的数据,还不足以满足一些特殊场景的需求,例如显示一个作者的所有书籍数量. 这时候就需要在已有数据基础上,聚合出这些没有的数据. 为查询集生产聚合: Django ...
- 【MM系列】SAP 关于更改物料的价格控制类型
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP 关于更改物料的价格控制类型 ...
- vim加脚本注释和文本加密
vim /etc/vimrc 一.李导版本 autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()" fun ...
- 【linux开发】ubuntu执行sudo apt-get update提示缺少公钥
ubuntu执行sudo apt-get update提示缺少公钥 提示信息如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 获取:1 http://arch ...
- vue插槽用法(极客时间Vue视频笔记)
vue插槽 插槽是用来传递复杂的内容,类似方法 <!DOCTYPE html> <html lang="en"> <head> <meta ...
- iScroll使用参考
分享是传播.学习知识最好的方法 以下这篇文章是iScroll.js官网的中文翻译,尽管自己英文不好,但觉得原作者们翻译的这个资料还是可以的,基本用法介绍清楚了.如果你英文比较好的话,可以看看官网的资料 ...
- JExcel - 学习总结(1)
1.什么是JExcel JExcel是Java对Excel进行操作的包,可以实现创建一个Excel并写入或读取Excel的数据等操作: JExcel的主要类为: (1)Workbook:工作簿 (2) ...
- Spark-Core RDD行动算子
1.reduce(func) 通过func函数聚集RDD 中的所有元素,先聚合分区内数据,再聚合分区间数据. scala> val rdd1 = sc.parallelize(1 to 100) ...
- nginx重新编译安装upload模块
由于php处理上传会出现超时,并且显示上传进度官方php不支持nginx+php,所以决定让nginx自己处理上传,我本地环境是mac上已经安装过nginx1.8.0,安装方式为brew,所以需要重新 ...