logging库
在Python的运行中,除去常规的print()函数调用,将我们需要的信息输出在控制台之外,还有另外一种更为规范化的信息记录模式,叫做日志。通过一定量的配置,可以很好地规范日志在控制台以及日志文件中进行详细的运行信息记录。而这一切在python中的实现,则是通过使用官方自带的logging库即可。
logging库基本用法
因为是官方自带库,所以在使用时直接调用即可,不需要额外进行安装。
''' logging库的基本应用: 1. 日志的基本等级(等级从低到高:debug < info < warning < error < critical) 2. 日志的相关配置 3. 日志在控制台的输出'''# 导入logging模块import logging# 日志器的相关配置项''' format日志输出格式内容: 1. asctime:时间格式 2. levelname:日志等级 3. filename:执行日志输出的文件名 4. leneno: 执行日志输出的代码行数 5. message:日志输出的内容'''logging.basicConfig( level=logging.DEBUG, # 日志输出等级配置,默认为warning级 # filemode='w', # 日志写入文件时的写入配置,默认为追加,也可设置为覆盖写入 filename='./log.log', # 日志保存文件名称,包含路径,若定义此项则日志输出会写入文件中 format='%(asctime)s %(levelname)s %(filename)s %(lineno)s %(message)s' # 日志输出格式设定)# 输出debug等级日志:此等级最低,一般用于调试logging.debug('this is debug')# 输出info等级日志:此等级较为常用,用于正常输出运行信息logging.info('this is info')# 输出warning等级日志:此等级一般用于输出一些警告,提示用户运行时会可能出现问题logging.warning('this is warning')# 输出error等级日志:运行过程中的error和exception都可由此等级输出,提示用户程序运行时已出现有问题logging.error('this is error')# 输出critical等级日志:严重问题,程序已经无法正常运行logging.critical('this is critical')
logging库的高级用法
通过logging库的组件实现日志的输出。
组件输出时,等级的设置优先级是处理器>记录器
''' logging高级应用: logging模块主要分为四大组件进行模块化应用 1. logger:记录器,提供应用程序能够直接使用的接口 2. handler:处理器,将记录器的内容发送到目的地 3. filter:过滤器,提供更好的粒度控制,决定哪些日志会被输出 4. formatter:格式化器,设置日志内容的组成结构和消息字段'''# 创建一个记录器,取名为hcc_log,也可以不取名,默认为rootlogger = logging.getLogger('hcc_log')# 设置记录器的日志等级logger.setLevel(logging.DEBUG)# 设置记录器的日志记录格式logger_format = logging.Formatter('%(asctime)s %(filename)s %(module)s %(levelname)s:%(message)s')# 创建一个流处理器(控制台输出)handler = logging.StreamHandler()# 设置控制台输出日志的等级handler.setLevel(logging.INFO)# 设置控制台输出日志格式handler.setFormatter(logger_format)# 创建一个文件处理器(可将日志写入文件),定义日志文件名称与路径file_handler = logging.FileHandler(filename='log.log')# 设置文件处理器的日志输出等级file_handler.setLevel(logging.DEBUG)# 设置文件处理器的日志输出格式file_handler.setFormatter(logger_format)# 将流处理器与文件处理器添加到控制器中logger.addHandler(handler)logger.addHandler(file_handler)# 输出日志logger.debug('this is logger.debug')logger.info('this is logger.info')
logging库的进阶用法
除去在代码层面直接定义日志相关的设定外,也可以通过配置文件的形式将所有日志的设置定义好,然后通过读取配置文件的方式来实现日志器的所有设置。
# 配置文件log.ini内容# 记录器[loggers]keys=root# 处理器[handlers]keys=fileHandler,streamHandler# 日志格式[formatters]keys=simpleFormatter# root记录器设置[logger_root]level=DEBUGhandlers=fileHandler,streamHandler# filehandler处理器的设置[handler_fileHandler]class=FileHandlerlevel=DEBUGformatter=simpleFormatterargs=('myLog.log','a','utf-8')# streamHandler处理器的设置[handler_streamHandler]class=StreamHandlerlevel=INFOformatter=simpleFormatter# simpleFormatter的格式定义[formatter_simpleFormatter]format=%(asctime)s %(filename)s %(module)s %(funcName)s %(levelname)s:%(message)s# 获取记录器的logger_demo.py文件内容# 导入logging.configimport logging.config# 读取配置文件logging.config.fileConfig('log.ini')# 通过getLogger获取记录器logger = logging.getLogger()# 日志内容输出logger.debug('this is debug')logger.info('this is info')
os库
os库是Python自带的官方库,有非常多的内容,能够处理与操作系统相关的常用路径/进程管理/环境参数设置等各类功能,在实际自动化测试过程中,我们对os库的使用也会有一些基本指令的调用。
import os''' os库可以调用cmd执行命令,也可以获取指定路径、文件夹、文件名称等相关操作系统的交互指令。 同时os也可以获取文件的路径,但在实际应用中pathlib会更为方便,所以可以不用os库的相关方法。'''# 返回路径及子路径、路径及子路径下的文件夹名称、路径及子路径下全部文件名称for path, dir, files in os.walk('./'): print(path) print(dir) print(files)# 判断指定路径及文件是否存在print(os.path.exists('./file_demo'))# 生成files_dir的文件夹os.mkdir('./files_dir')# 调用cmd窗体执行指令os.system('python --version')
pathlib库
pathlib库用于获取目标文件的相对路径与绝对路径,在操作文件的过程中,通过pathlib获取路径可以更好更灵活地指定到对应的文件
import pathlib''' pathlib用于获取指定文件的相对路径与绝对路径。 生成的路径结果,可以通过parents方法获取到父级目录,通过下标来指定父级目录的值,parents[0]为上一级,parents[1]为上上级 以此类推,最高级为工程根目录。 通过resolv()方法生成路径值。'''# 获取1.txt的路径path = pathlib.Path('./file_demo/1.txt')# 输出路径值print(path)# 获取1.txt的上级目录,通过resolve()方法生成路径,由print打印print(path.parents[1].resolve())
pymysql库
pymysql库,是在python中非常常用的操作mysql数据库的第三方库,可以通过pymysql库非常方便地操作mysql数据库,实现数据的读取,在自动化测试过程中,也可以基于此库实现数据库数据驱动的内容和读取mysql数据库数据进行测试结果的校验等。
环境安装
因为是第三方库,python默认不带有此环境,所以需要通过指令进行安装。
pymysql基本操作
通过pymysql操作数据库,需要按照pymysql的定义来进行,从连接数据库到执行sql到结果的获取,都有相关的方法进行操作。
''' pymysql应用'''import tracebackimport pymysqlcountry_code = input('请输入国家编码')# mysql数据库的连接信息db_info = { 'host': '127.0.0.1', # mysql的服务端ip地址 'port': 3306, # mysql的端口信息 'user': 'root', # mysql的登录账户 'password': '123456', # mysql的登录密码 'database': 'world' # mysql连接的数据库名称}# 连接mysql数据库conn = pymysql.connect(**db_info)# 生成游标,默认数据结果以元组的格式返回,可定义cursor参数,让数据结果以字典格式返回cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # pymysql.cursors.DictCursor默认无法自动补全,需手动填写# 基本的sql语句执行方法,安全性相对较低,无法防止sql注入sql = 'select * from cIty where CountryCode="{}"'.format(country_code)# 基于execute传参的形式进行sql执行,可将输入内容参数化,有效防止sql注入,提升安全性sql1 = 'select id,name,countrycode from city where CountryCode= %s'try: # 单个参数传递可直接传,若有多个参数,则需通过元组格式将所有参数打包 cursor.execute(sql1, country_code) result = cursor.fetchall() # 获取sql执行后的所有返回结果 # result_one = cursor.fetchone() # 获取sql执行后的一条返回结果 print(sql) print(result) # print(result_one) # 获取返回的一条结果 # 因为cursor是游标,所以可以向后移动或向前回滚,再次调用fetchone()则会获取第二条记录。 # result_one = cursor.fetchone() # 再次获取数据记录 # print(result_one) # 获取返回的第二条结果 # 游标因为是移动的,所以可以回滚或者前移,通过scroll()方法实现 # cursor.scroll(1, 'relative') # 向后移动一位 # result_one = cursor.fetchone() # print(result_one) # cursor.scroll(1, 'absolute') # 向前回滚一位 # result_one1 = cursor.fetchone() # print(result_one1) # for id, name, countrycode in result: # print(id) # print(name) # print(countrycode)except: traceback.print_exc() conn.rollback() # 若sql执行失败或代码报错,则回滚本次操作,避免对数据库造成影响finally: # 关闭数据库与游标资源,确保数据库连接正常结束 cursor.close() conn.close()
pymysql修改数据操作
通过pymysql库对数据库内容进行查询时,不会涉及到数据的修改,所以不需要进行二次确认。但是在进行增删改操作时,因为对原有数据表进行了对应修改,所以在执行时需要二次确认才可以修改生效。
''' 常规的查询sql语句,因为不会涉及到数据的变动,所以在执行时不需要进行二次确认,而修改数据 的sql语句,像是delete、update、insert into这一类型,因为会对数据表进行修改,所以在 执行此类sql语句时,需要通过数据库连接对象来调用commit()来进行二次确认,如果不调用,则 本次修改不会对数据库生效。 如果怕忘记调用commit()方法,或者修改类型的sql语句调用较多,也可以在数据库连接信息中配置 自动commit的选项。'''import pymysql# mysql数据库的连接信息db_info = { 'host': '127.0.0.1', # mysql的服务端ip地址 'port': 3306, # mysql的端口信息 'user': 'root', # mysql的登录账户 'password': 'root', # mysql的登录密码 'database': 'test_db', # mysql连接的数据库名称 'autocommit': True # mysql修改类型sql执行的自动commit,默认为False}# 连接数据库conn = pymysql.connect(**db_info)# 创建游标cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)# 定义修改数据的sql语句sql = 'update user_info set username=%s where id=1'# 通过游标执行修改数据sql语句cursor.execute(sql, 'huangcaicai1231')# 调用连接对象进行commit操作,确认本次数据修改行为# conn.commit()# 关闭连接与游标conn.close()cursor.close()
pymysql配置文件设置
因为数据库相关信息内容比较多,直接将内容写在代码中不便于平时的管理,也不够灵活,所以可以将相关信息配置在配置文件中,通过调用配置文件信息来实现数据库配置项的获取。而这个操作,则需要使用到配置文件ini和配置文件读取的configparser库了。
# mysql的.ini文件内容[mysql]HOST=127.0.0.1PORT=3306USER=rootPASSWORD=rootDATABASE=test_db# 配置内容读取的.py文件内容''' 在Python中,配置文件常用的是ini后缀名的文件,在定义配置文件后,如果想要读取配置文件的内容,则 需要调用configparser库来实现。对于该库的其他应用不需要过多了解,主要在于读取ini文件的相关操作'''import configparser# 定义配置内容读取的函数def read_conf(): # 创建ConfigParser()对象 conf = configparser.ConfigParser() # 读取conf.ini的数据库配置文件 conf.read('./conf.ini') #获取配置项内容,转型为字典格式 data = dict(conf.items('mysql')) # 通过循环将字典内容全部读取。 for key in data.keys(): # 因为数据库的端口项为int,而配置文件读取默认为str,所以对port项进行强制转型 if key == 'port': data[key] = int(data[key]) # 将最终的字典格式的值返回。 return data
SMTP库
smtplib库是python自带有的邮件发送库,可以通过对smtplib库及email库的相关内容调用,实现自动发送邮件的功能。邮件发送前,根据发送人邮件类型,需要提前在邮箱服务中启动SMTP服务,生成授权码,才可以授权调用smtplib库实现邮件的发送
发送文本邮件
import smtplibfrom email.header import Headerfrom email.mime.text import MIMEText# 邮箱基本信息sender = '2375154305@qq.com' # 发送人receiver = '15414086@qq.com' # 接收人pass_code = '你的邮箱授权码' # 邮箱授权码# 连接邮箱服务smtp_con = smtplib.SMTP('smtp.qq.com', 25) # smtp服务的默认地址是smtp.xx.com,端口为25# 文本邮件正文text = '这是一封文本邮件的正文内容'content = MIMEText(text, 'plain', 'utf-8')# 设置发送与接收人content['From'] = sendercontent['To'] = receiver# 设置邮件主体email_theme = '这是文本邮件的主题'content['Subject'] = Header(email_theme, 'utf-8')# 发送邮件smtp_con.login(sender, pass_code) # 登录smtp_con.sendmail(sender, receiver, content.as_string())# 释放资源smtp_con.quit()
发送HTML格式邮件
import smtplibfrom email.header import Headerfrom email.mime.text import MIMEText# 邮箱基本信息sender = '2375154305@qq.com' # 发送人receiver = '15414086@qq.com' # 接收人pass_code = '你的邮箱授权码' # 邮箱授权码# 连接邮箱服务smtp_con = smtplib.SMTP('smtp.qq.com', 25) # smtp服务的默认地址是smtp.xx.com,端口为25# 文本邮件正文html = ''' <p>这是一封HTML邮件</p> <p><a href="http://www.baidu.com">这是百度</a></p>'''content = MIMEText(html, 'html', 'utf-8')# 设置发送与接收人content['From'] = sendercontent['To'] = receiver # 如果有多个发件人,则可以通过','.join(receiver)的方式用,分割收件人。# 设置邮件主体email_theme = '这是html邮件的主题'content['Subject'] = Header(email_theme, 'utf-8')# 发送邮件smtp_con.login(sender, pass_code) # 登录smtp_con.sendmail(sender, receiver, content.as_string())# 释放资源smtp_con.quit()
发送带有附件的邮件
import smtplibfrom email.header import Headerfrom email.mime.multipart import MIMEMultipartfrom email.mime.text import MIMEText# 邮箱基本信息sender = '2375154305@qq.com' # 发送人receiver = '15414086@qq.com' # 接收人pass_code = '你的邮箱授权码' # 邮箱授权码# 创建一个带附件邮件对象mail = MIMEMultipart()# 连接邮箱服务smtp_con = smtplib.SMTP('smtp.qq.com', 25) # smtp服务的默认地址是smtp.xx.com,端口为25# 文本邮件正文text = '这是邮件的正文内容'content = MIMEText(text, 'plain', 'utf-8')# 设置发送与接收人mail['From'] = sendermail['To'] = receiver# 设置邮件主体email_theme = '这是邮件的主题'mail['Subject'] = Header(email_theme, 'utf-8')# 添加正文到邮件内mail.attach(content)# 创建附件att1 = MIMEText(open('aaa.png', 'rb').read(), 'base64', 'utf-8')att1.add_header('Content-Type', 'octet-stream')att1.add_header('Content-Disposition', 'attachment', filename="图片.png")# 将附件添加到邮件中mail.attach(att1)# 发送邮件smtp_con.login(sender, pass_code) # 登录smtp_con.sendmail(sender, receiver, mail.as_string()) # 发送邮件# 释放资源smtp_con.quit()
配置收件人发件人信息
因为邮件发送时,收件人与发件人基本固定,所以也可以配置到配置文件中,直接获取。依旧也是通过configparser库来实现内容的获取。
# conf.ini文件配置相关信息[email]sender=2375154305@qq.comreceiver=2375154305@qq.com,15414086@qq.com# read_conf.py文件获取配置信息''' 获取配置文件中的发件人与收件人信息'''import configparserdef read(): conf = configparser.ConfigParser() conf.read('conf.ini') info = dict(conf.items('email')) return info# send.py文件中实现发件人与收件人信息的获取# 邮箱基本信息info = read_conf.read()sender = info['sender'] # 发送人receiver = info['receiver'] # 接收人
关注作者微信公众号 —《蜀道衫》
了解更多软件测试开发知识以及最新面试宝典