title: 如何正确使用日志Log

date: 2015-01-08 12:54:46

categories: [Python]

tags: [Python,log]

文章首发地址:http://kingname.info

这篇文章不会教你在技术角度上使用log,而是告诉你为什么要使用log日志功能。

为什么要使用Log

使用微信控制你的电脑这篇文章中,我写好了电脑端的程序,使用py2exe生成可执行文件,并把它们发送给我的朋友让他们进行测试。但是他们把_config.ini设置好以后,运行程序就看到一个黑色窗口一闪而过。或者有些人一开始看到程序能正常登陆邮箱,但是准备执行命令的时候,窗口自动关闭。

由于没有日志记录程序的运行状态,我根据他们的描述很难定位到错误在哪个地方。于是折腾了一个下午。

这个时候,我觉得添加一个日志的功能迫在眉睫。

哪些地方应该用Log

目前网上能找到的关于如何使用日志的文章,全部都是从技术角度讲怎么使用log:在XX地方应该先imort logging,然后basicconfig设定XX内容。可是我现在的问题是:

  • 应该在程序的哪些地方添加日志的输出?
  • 输出什么内容?
  • 如何输出才能以方便我的监控程序的运行情况?

于是我只有自己摸索。因此,以下内容是我自己摸索出来的野路子,可能会有错漏。希望有经验的朋友能给我指正,非常感谢。

这些地方应该用Log

使用使用微信控制你的电脑文章中涉及到的例子

程序入口代码如下:

if __name__=='__main__':
init()
print u'等待接收命令'
logging.info(u'初始化完成。')
while 1:
time.sleep(int(time_limit)) #每5分钟检查一次邮箱
accp_mail()

以上代码表示程序运行以后,首先执行init()函数,于是如果init()初始化没有什么问题,成功执行完成以后,就应该在日志中输出“初始化完成”,然后进入接收邮件的循环。如果程序窗口运行以后一闪而过,而且生成的日志中没有初始化完成这样的字眼,那就说明问题出在初始化上面。

然而初始化函数里面代码也有很多,又如何知道是初始化程序里面的什么地方出问题了呢?

所以,再初始化函数里面,也应该有一定的日志记录。

再看初始化函数的代码:

def init():
global username,password,host,boss_email,time_limit try:
f = open('_config.ini','r')
except IOError,e:
logging.error(e)
exit() info = f.readlines()
try:
host = re.search('host:(.*?)\n',info[0],re.S).group(1)
username = re.search('username:(.*?com)',info[1],re.S).group(1)
password = re.search('password:(.*?)\n',info[2],re.S).group(1)
boss_email = re.search('boss_email:(.*?com)',info[3],re.S).group(1)
time_limit = re.search('time_limit:(.*?)\n',info[4],re.S).group(1)
except Exception,e:
logging.error(e) logging.info(u'打开配置文件成功。。。') #将命令生成字典,便于查询
command_start = info.index('<command>\n')
command_end = info.index('</command>\n')
for each in info[command_start+1:command_end]:
command = each.split('=')
command_dict[command[0]] = command[1] logging.info(command_dict) open_start = info.index('<open_file>\n')
open_end = info.index('</open_file>\n')
for each in info[open_start+1:open_end]:
open_file = each.split('=')
open_dict[open_file[0]] = open_file[1][:-1] logging.info(open_dict) f.close()

在这段代码中,我使用try except命令捕获异常,如果发生异常,就使用logging.error将错误写入日志中。例如当_config.ini被改名了或者被删除的时候,程序就会报错,而通过日志就能发现这个错误。

经过上面的代码,如果在初始化的过程中出错,就可以很快确定问题出在什么地方。

初始化完成以后,进入邮件接收阶段。

def accp_mail():
logging.info(u'开始检查邮箱')
try:
pp = poplib.POP3_SSL(host)
pp.set_debuglevel(1)
pp.user(username)
pp.pass_(password)
ret = pp.list()
logging.info(u'登录邮箱成功。')
except Exception,e:
logging.error(e)
exit() logging.info(u'开始抓取邮件。')
try:
down = pp.retr(len(ret[1]))
logging.info(u抓取邮件成功。'')
except Exception,e:
logging.error(e)
exit() logging.info(u'开始抓取subject和发件人')
try:
subject = re.search("Subject: (.*?)',",str(down[1]).decode('utf-8'),re.S).group(1)
sender = re.search("'X-Sender: (.*?)',",str(down[1]).decode('utf-8'),re.S).group(1)
logging.info(u'抓取subject和发件人成功')
except Exception,e:
logging.error(e)
exit() if subject != 'pass':
if sender == boss_email:
DealCommand(subject)
pp.quit()

以上这段代码,对邮箱的登录与邮件的读取均作了监控,一旦有某个环节出了问题,就会体现在日志中。

通过在登录环节的try except返回的错误日志,发现有很多朋友无法登录邮箱,而密码用户名都没有错,从而推断是没有在新浪邮箱的账户控制里面打开客服端接收POP3和SMTP的功能。

再来看DealCommand()函数:

def DealCommand(subject):
logging.info(u'开始处理命令。')
send_mail('pass','slave')
if subject in command_dict:
logging.info(u'执行命令')
try:
command = command_dict[subject]
os.system(command)
send_mail('Success','boss')
logging.info(u'执行命令成功')
except Exception,e:
logging.error(e)
send_mail('error','boss',e)
elif subject in open_dict:
logging.info(u'打开文件')
try:
open_file = open_dict[subject]
win32api.ShellExecute(0, 'open', open_file, '','',1)
send_mail('Success','boss')
logging.info(u'打开文件成功')
except Exception,e:
logging.error(e)
send_mail('error','boss',e)
else:
send_mail('error','boss','no such command')

执行命令的地方可能会出错,于是果断使用try except捕获错误。并使用日志记录。

最后是send_mail()函数:

def send_mail(subject,flag,body='Success'):

        msg = MIMEText(body,'plain','utf-8')#中文需参数‘utf-8’,单字节字符不需要
msg['Subject'] = subject
msg['from'] = username
logging.info('开始配置发件箱。')
try:
handle = smtplib.SMTP('smtp.sina.com', 25)
handle.login(username,password)
logging.info('发件箱配置成功')
except Exception,e:
logging.error(e)
exit() logging.info(u'开始发送邮件'+ 'to' + flag)
if flag == 'slave':
try:
handle.sendmail(username,username, msg.as_string())
logging.info(u'发送邮件成功')
except Exception,e:
logging.error(e)
exit()
elif flag == 'boss':
try:
handle.sendmail(username,boss_email, msg.as_string())
logging.info(u'发送邮件成功')
except Exception,e:
logging.error(e)
exit() handle.close()
logging.info(u'发送邮件结束'+flag)

这里对邮件发件的部分需要特别仔细的错误捕获,然后记录进入日志中。

完整的代码见:https://github.com/kingname/MCC.git中的auto.py

总结

需要使用日志记录的地方大致有一下几处:

  • 所有输入输出处,无论是从文件输入还是从网络等其他地方输入
  • 执行命令处
  • 调用函数处

PS

这里我对一般信息的记录使用了info,实际上,一般用作调试的话,是使用debug更多。

需要用户输入的地方,总会有想不到的错误,多小心都不为过。例如,用户可能会把time_limit设定为一个全角数字。而本文中就没有捕获这种问题到日志中。所以如果不放心的话,还可以更进一步的细化日志。

如何正确使用日志Log的更多相关文章

  1. Expo大作战(六)--expo开发模式,expo中exp命令行工具,expo中如何查看日志log,expo中的调试方式

    简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,将全部来与官网 我猜去全部机翻+个人 ...

  2. 一件关于数据库日志log的无聊事情

    为何说是无聊的记录呢? 因为事先把问题想复杂了,事后发现的时候觉得更是无聊的行为.还是写下来,毕竟很少弄这么无聊的事情. 事情起因是需要给服务器做性能基数(baseline),用sqldiag 提取了 ...

  3. C# 分析 IIS 日志(Log)

    由于最近又要对 IIS日志 (Log) 分析,以便得出各个搜索引擎每日抓取的频率,所以这两天一直在尝试各个办法来分析 IIS 日志 (Log),其中尝试过:导入数据库.Log parser.Powse ...

  4. cocos2d-js 写日志log 查看日志log Android调试查看log

    1 输出日志的方式,当然是cc.log了 2 如何查看日志?        a)如果小程序可以先在浏览器上跑,例如用chrome,在控制台就可以看到输出的log:        b)如果在真机上调试, ...

  5. [日志log] 常用log日志记录方式对比和详解

    1.现在都有哪些记录日志的方法 A.java.util.logging.Logger - 使用详解 B.log4j - 使用详解 C.SLF4J(simple logging Facade for J ...

  6. JMeter-显示调试日志log

    JMeter-调试日志记录 参考文档:https://jmeter.apache.org/usermanual/hints_and_tips.html 大多数测试元素包括调试日志记录. 如果从GUI运 ...

  7. 日志log

    public class LoggerHelper { private static Queue<string> qMsg = null; private static string lo ...

  8. sql2008r 收缩数据库日志log文件;删除errorlog文件的方法

    1.清空log文件,以减少数据库文件log所占的空间 USE dbname1 ; GO ALTER DATABASE dbname1 SET RECOVERY SIMPLE;--设置简单恢复模式 GO ...

  9. 正确的选择log级别

    开发一个应用,日志的重要性不言而喻.然而有时会发现日志中会出现大量的垃圾日志.所谓垃圾日志,就是不需要知道的日志,或者这些日志对于应用查看.跟踪没有什么作用.也正是(但不仅仅是)出于这些问题的考量,常 ...

随机推荐

  1. SQL Server表分区

    什么是表分区 一般情况下,我们建立数据库表时,表数据都存放在一个文件里. 但是如果是分区表的话,表数据就会按照你指定的规则分放到不同的文件里,把一个大的数据文件拆分为多个小文件,还可以把这些小文件放在 ...

  2. Android Studio 多个编译环境配置 多渠道打包 APK输出配置

    看完这篇你学到什么: 熟悉gradle的构建配置 熟悉代码构建环境的目录结构,你知道的不仅仅是只有src/main 开发.生成环境等等环境可以任意切换打包 多渠道打包 APK输出文件配置 需求 一般我 ...

  3. ABP文档 - Mvc 控制器

    文档目录 本节内容: 简介 AbpController基类 本地化 其它 过滤 异常处理和结果包装 审计日志 验证 授权 工作单元 反伪造 模型绑定器 简介 ABP通过nuget包Abp.Web.Mv ...

  4. input[tyle="file"]样式修改及上传文件名显示

    默认的上传样式我们总觉得不太好看,根据需求总想改成和上下结构统一的风格…… 实现方法和思路: 1.在input元素外加a超链接标签 2.给a标签设置按钮样式 3.设置input[type='file' ...

  5. 手动添加kdump

    背景:     Linux嵌入式设备内核挂死后,无法自动重启,需要手动重启.而且如果当时没有连串口的话,就无法记录内核挂死时的堆栈,所以需要添加一种方式来记录内核挂死信息方便以后调试使用.设备中增加k ...

  6. IE8/9 本地预览上传图片

    本地预览的意思是,在选择图片之后先不上传到服务器,而是由一个<img>标签来预览本地的图片,非 IE8/9 浏览器可以从<input type="file"/&g ...

  7. PHP之时间和日期函数

    // 时间日期函数 Time <?php date_default_timezone_set('UTC'); // 获取当前时间的时间戳 $time0 = mktime(); $time1 = ...

  8. 数据图表插件Echarts(一)

    一.引言 最近做一个智慧城市项目,项目中需要图表和报表进行数据分析,从网上找了很多,最后找到了百度开放的echarts,一个很强大的插件. 二.介绍 ECharts,缩写来自Enterprise Ch ...

  9. JQuery实现表格的增加行和删除行

    利用JQuery实现datatables插件的增加和删除行操作 在学习过程中遇到了这个利用JQuery对表格行的增加和删除,特记录下来以供初学者参考. 下面是主要的代码: <meta http- ...

  10. 在 Windows7 上按照 MySQL5.7

    在 Windows7 上按照 MySQL5.7 1.从官网下载最新版本的 MySQL,这里下载的是 mysql-5.7.17-win32: 2.将下载的 mysql-5.7.17-win32.zip ...