-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path2016-05-29-python-log.html
322 lines (227 loc) · 54.7 KB
/
2016-05-29-python-log.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Python logging 模块封装 | Hm's Blog</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="description" content="python自带的记录日志模块 logging 非常强大,但是每次写程序都要写很多东西来配置使用,体验不怎么友好,花时间封装在一个文件里面,用的时候直接调用,并且提供配置接口保留其强大的功能还是非常有必要的。
logging介绍Python的logging模块提供了通用的日志系统,可以方便第三方模块或者是应用使用。这个模块提供不同的日志级别,并可以采用不同的方式记录日志,比如文件,HTTP GET">
<meta property="og:type" content="article">
<meta property="og:title" content="Python logging 模块封装">
<meta property="og:url" content="http://huangming.github.io/2016-05-29-python-log.html">
<meta property="og:site_name" content="Hm's Blog">
<meta property="og:description" content="python自带的记录日志模块 logging 非常强大,但是每次写程序都要写很多东西来配置使用,体验不怎么友好,花时间封装在一个文件里面,用的时候直接调用,并且提供配置接口保留其强大的功能还是非常有必要的。
logging介绍Python的logging模块提供了通用的日志系统,可以方便第三方模块或者是应用使用。这个模块提供不同的日志级别,并可以采用不同的方式记录日志,比如文件,HTTP GET">
<meta property="og:updated_time" content="2016-07-01T08:11:51.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Python logging 模块封装">
<meta name="twitter:description" content="python自带的记录日志模块 logging 非常强大,但是每次写程序都要写很多东西来配置使用,体验不怎么友好,花时间封装在一个文件里面,用的时候直接调用,并且提供配置接口保留其强大的功能还是非常有必要的。
logging介绍Python的logging模块提供了通用的日志系统,可以方便第三方模块或者是应用使用。这个模块提供不同的日志级别,并可以采用不同的方式记录日志,比如文件,HTTP GET">
<meta name="twitter:creator" content="@hmorz">
<link rel="alternative" href="/atom.xml" title="Hm's Blog" type="application/atom+xml">
<link rel="icon" href="/favicon.png">
<!-- <link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css"> -->
<link rel="stylesheet" href="/css/font-awesome.min.css">
<link href="/css/font-quigleywiggly.css" rel="Stylesheet" type="text/css" />
<link rel="stylesheet" href="/css/style.css" type="text/css">
<script src="/js/jquery-1.4.2.min.js" type="text/javascript"></script>
<script src="/js/girls.js" type="text/javascript"></script>
<script type="text/javascript" charset="utf-8" src="/js/weather.js"></script>
<link href="http://huangming.github.io/stylesheets/main.css" rel="stylesheet" media="all"/>
<link href="http://huangming.github.io/images/weather/default/julying-weather.css" rel="stylesheet" media="all"/>
<!--
-->
</head>
<body>
<div id="container">
<div id="wrap">
<header id="header">
<div id="banner"></div>
<div id="header-outer" class="outer">
<div id="header-title" class="inner">
<h1 id="logo-wrap">
<a href="/" id="logo">Hm's Blog</a>
</h1>
<h2 id="subtitle-wrap">
<a href="/" id="subtitle">I am here</a>
</h2>
</div>
<div id="header-inner" class="inner">
<nav id="main-nav">
<a id="main-nav-toggle" class="nav-icon"></a>
<a class="main-nav-link" href="/">Home</a>
<a class="main-nav-link" href="/archives">Archives</a>
<a class="main-nav-link" href="/vimwiki">Wiki</a>
</nav>
<nav id="sub-nav">
<a id="nav-rss-link" class="nav-icon" href="/atom.xml" title="RSS Feed"></a>
<a id="nav-search-btn" class="nav-icon" title="Search"></a>
<div id="search-form-wrap">
<form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" results="0" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit"></button><input type="hidden" name="sitesearch" value="http://huangming.github.io"></form>
</div>
</nav>
</div>
</div>
</header>
<div class="outer">
<section id="main"><article id="post-python-log" class="article article-type-post" itemscope itemprop="blogPost">
<!-- <div class="article-meta"> -->
<!-- <a href="/2016-05-29-python-log.html" class="article-date">
<time datetime="2016-05-29T05:22:14.000Z" itemprop="datePublished">2016-05-29</time>
</a> -->
<!--
<div class="article-category">
<a class="article-category-link" href="/categories/python/">python</a>
</div>
-->
<!-- </div> -->
<div class="article-inner">
<header class="article-header">
<h1 class="article-title" itemprop="name">
Python logging 模块封装
</h1>
<div class="article-meta">
<a href="/2016-05-29-python-log.html" class="article-date">
<time datetime="2016-05-29T05:22:14.000Z" itemprop="datePublished">2016-05-29</time>
</a>
<div class="article-category">
<a class="article-category-link" href="/categories/python/">python</a>
</div>
</div>
</header>
<div class="article-entry" itemprop="articleBody">
<p>python自带的记录日志模块 <a href="https://docs.python.org/3/library/logging.html#module-logging" target="_blank" rel="external">logging</a> 非常强大,但是每次写程序都要写很多东西来配置使用,体验不怎么友好,花时间封装在一个文件里面,用的时候直接调用,并且提供配置接口保留其强大的功能还是非常有必要的。</p>
<h2 id="logging介绍">logging介绍</h2><p>Python的logging模块提供了通用的日志系统,可以方便第三方模块或者是应用使用。这个模块提供不同的日志级别,并可以采用不同的方式记录日志,比如文件,HTTP GET/POST,SMTP,Socket等,甚至可以自己实现具体的日志记录方式。</p>
<p>logging模块与log4j的机制是一样的,只是具体的实现细节不同。模块提供logger,handler,filter,formatter。</p>
<ul>
<li>logger:提供日志接口,供应用代码使用。</li>
<li>handler:将日志记录(log record)发送到合适的目的地(destination),比如文件,socket,cmd等。一个logger对象可以通过addHandler方法添加0到多个handler,每个handler又可以定义不同日志级别,以实现日志分级过滤显示。每个handler还可以单独设置自己的formatter格式。</li>
<li>filter:提供一种优雅的方式决定一个日志记录是否发送到handler。</li>
<li>formatter:指定日志记录输出的具体格式。</li>
</ul>
<p>与log4j类似,logger,handler和日志消息的调用可以有具体的日志级别(Level),只有在日志消息的级别大于logger和handler的级别才会呈现。</p>
<p>默认的日志级别设置为<code>WARNING</code>(日志级别等级<code>CRITICAL</code> > <code>ERROR</code> > <code>WARNING</code> > <code>INFO</code> > <code>DEBUG</code> > <code>NOTSET</code>), 小于WARNING级别的日志都不输出, 大于等于WARNING级别的日志都会输出。<br><a id="more"></a><br>更多可以自己搜索一下。</p>
<h2 id="封装成log-py">封装成log.py</h2><p>源码在github上有:<a href="https://github.com/huangming/python_log" target="_blank" rel="external">python_log</a></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding: utf-8 -*-</span></span><br><span class="line"><span class="comment"># Last Update: 2015/06/30 10:53:52</span></span><br><span class="line"><span class="comment"># file mylog.py</span></span><br><span class="line">__author__ = <span class="string">"Mingo <[email protected]>"</span></span><br><span class="line">__status__ = <span class="string">"Development"</span></span><br><span class="line"> </span><br><span class="line">__all__ = [<span class="string">'set_logger'</span>, <span class="string">'debug'</span>, <span class="string">'info'</span>, <span class="string">'warning'</span>, <span class="string">'error'</span>,</span><br><span class="line"> <span class="string">'critical'</span>, <span class="string">'exception'</span>]</span><br><span class="line"> </span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">import</span> traceback</span><br><span class="line"><span class="keyword">import</span> logging</span><br><span class="line"><span class="keyword">import</span> logging.handlers</span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ColoredFormatter</span><span class="params">(logging.Formatter)</span>:</span></span><br><span class="line"> <span class="string">'''A colorful formatter.'''</span></span><br><span class="line"> </span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, fmt = None, datefmt = None)</span>:</span></span><br><span class="line"> logging.Formatter.__init__(self, fmt, datefmt)</span><br><span class="line"> </span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">format</span><span class="params">(self, record)</span>:</span></span><br><span class="line"> <span class="comment"># Color escape string</span></span><br><span class="line"> COLOR_RED=<span class="string">'\033[1;31m'</span></span><br><span class="line"> COLOR_GREEN=<span class="string">'\033[1;32m'</span></span><br><span class="line"> COLOR_YELLOW=<span class="string">'\033[1;33m'</span></span><br><span class="line"> COLOR_BLUE=<span class="string">'\033[1;34m'</span></span><br><span class="line"> COLOR_PURPLE=<span class="string">'\033[1;35m'</span></span><br><span class="line"> COLOR_CYAN=<span class="string">'\033[1;36m'</span></span><br><span class="line"> COLOR_GRAY=<span class="string">'\033[1;37m'</span></span><br><span class="line"> COLOR_WHITE=<span class="string">'\033[1;38m'</span></span><br><span class="line"> COLOR_RESET=<span class="string">'\033[1;0m'</span></span><br><span class="line"> <span class="comment"># Define log color</span></span><br><span class="line"> LOG_COLORS = {</span><br><span class="line"> <span class="string">'DEBUG'</span>: <span class="string">'%s'</span>,</span><br><span class="line"> <span class="string">'INFO'</span>: COLOR_GREEN + <span class="string">'%s'</span> + COLOR_RESET,</span><br><span class="line"> <span class="string">'WARNING'</span>: COLOR_YELLOW + <span class="string">'%s'</span> + COLOR_RESET,</span><br><span class="line"> <span class="string">'ERROR'</span>: COLOR_RED + <span class="string">'%s'</span> + COLOR_RESET,</span><br><span class="line"> <span class="string">'CRITICAL'</span>: COLOR_RED + <span class="string">'%s'</span> + COLOR_RESET,</span><br><span class="line"> <span class="string">'EXCEPTION'</span>: COLOR_RED + <span class="string">'%s'</span> + COLOR_RESET,</span><br><span class="line"> }</span><br><span class="line"> level_name = record.levelname</span><br><span class="line"> msg = logging.Formatter.format(self, record)</span><br><span class="line"> <span class="keyword">return</span> LOG_COLORS.get(level_name, <span class="string">'%s'</span>) % msg</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Log</span><span class="params">()</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, filename = None, mode = <span class="string">'a'</span>,</span><br><span class="line"> cmdlevel=<span class="string">'DEBUG'</span>,</span><br><span class="line"> filelevel=<span class="string">'INFO'</span>,</span><br><span class="line"> cmdfmt = <span class="string">'[%(asctime)s] %(filename)s line:%(lineno)d %(levelname)-8s%(message)s'</span>,</span><br><span class="line"> filefmt = <span class="string">'[%(asctime)s] %(levelname)-8s%(message)s'</span>,</span><br><span class="line"> cmddatefmt = <span class="string">'%H:%M:%S'</span>,</span><br><span class="line"> filedatefmt = <span class="string">'%Y-%m-%d %H:%M:%S'</span>,</span><br><span class="line"> backup_count = <span class="number">0</span>, limit = <span class="number">20480</span>, when = None, colorful = False)</span>:</span></span><br><span class="line"> self.filename = filename</span><br><span class="line"> <span class="keyword">if</span> self.filename <span class="keyword">is</span> <span class="keyword">None</span>:</span><br><span class="line"> self.filename = getattr(sys.modules[<span class="string">'__main__'</span>], <span class="string">'__file__'</span>, <span class="string">'log.py'</span>)</span><br><span class="line"> self.filename = os.path.basename(self.filename.replace(<span class="string">'.py'</span>, <span class="string">'.log'</span>))</span><br><span class="line"> <span class="comment">#self.filename = os.path.join('/tmp', self.filename)</span></span><br><span class="line"> self.mode = mode</span><br><span class="line"> self.cmdlevel = cmdlevel</span><br><span class="line"> self.filelevel = filelevel</span><br><span class="line"> <span class="keyword">if</span> isinstance(self.cmdlevel, str):</span><br><span class="line"> self.cmdlevel = getattr(logging, self.cmdlevel.upper(), logging.DEBUG)</span><br><span class="line"> <span class="keyword">if</span> isinstance(self.filelevel, str):</span><br><span class="line"> self.filelevel = getattr(logging, self.filelevel.upper(), logging.DEBUG)</span><br><span class="line"> self.filefmt = filefmt</span><br><span class="line"> self.cmdfmt = cmdfmt</span><br><span class="line"> self.filedatefmt = filedatefmt</span><br><span class="line"> self.cmddatefmt = cmddatefmt</span><br><span class="line"> self.backup_count = backup_count</span><br><span class="line"> self.limit = limit</span><br><span class="line"> self.when = when</span><br><span class="line"> self.colorful = colorful</span><br><span class="line"> self.logger = <span class="keyword">None</span></span><br><span class="line"> self.streamhandler = <span class="keyword">None</span></span><br><span class="line"> self.filehandler = <span class="keyword">None</span></span><br><span class="line"> <span class="keyword">if</span> self.cmdlevel > <span class="number">10</span>:</span><br><span class="line"> self.filefmt = <span class="string">'[%(asctime)s] %(levelname)-8s%(message)s'</span></span><br><span class="line"> self.cmdfmt = <span class="string">'[%(asctime)s] %(levelname)-8s%(message)s'</span></span><br><span class="line"> self.cmddatefmt = <span class="string">'%Y-%m-%d %H:%M:%S'</span></span><br><span class="line"> self.set_logger(cmdlevel = self.cmdlevel)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">init_logger</span><span class="params">(self)</span>:</span></span><br><span class="line"> <span class="string">'''Reload the logger.'''</span></span><br><span class="line"> <span class="keyword">if</span> self.logger <span class="keyword">is</span> <span class="keyword">None</span>:</span><br><span class="line"> self.logger = logging.getLogger()</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> logging.shutdown()</span><br><span class="line"> self.logger.handlers = []</span><br><span class="line"> self.streamhandler = <span class="keyword">None</span></span><br><span class="line"> self.filehandler = <span class="keyword">None</span></span><br><span class="line"> self.logger.setLevel(logging.DEBUG)</span><br><span class="line"> </span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">add_streamhandler</span><span class="params">(self)</span>:</span></span><br><span class="line"> <span class="string">'''Add a stream handler to the logger.'''</span></span><br><span class="line"> self.streamhandler = logging.StreamHandler()</span><br><span class="line"> self.streamhandler.setLevel(self.cmdlevel)</span><br><span class="line"> <span class="keyword">if</span> self.colorful:</span><br><span class="line"> formatter = ColoredFormatter(self.cmdfmt, self.cmddatefmt)</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> formatter = logging.Formatter(self.cmdfmt, self.cmddatefmt,)</span><br><span class="line"> self.streamhandler.setFormatter(formatter)</span><br><span class="line"> self.logger.addHandler(self.streamhandler)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">add_filehandler</span><span class="params">(self)</span>:</span></span><br><span class="line"> <span class="string">'''Add a file handler to the logger.'''</span></span><br><span class="line"> <span class="comment"># Choose the filehandler based on the passed arguments</span></span><br><span class="line"> <span class="keyword">if</span> self.backup_count == <span class="number">0</span>: <span class="comment"># Use FileHandler</span></span><br><span class="line"> self.filehandler = logging.FileHandler(self.filename, self.mode)</span><br><span class="line"> <span class="keyword">elif</span> self.when <span class="keyword">is</span> <span class="keyword">None</span>: <span class="comment"># Use RotatingFileHandler</span></span><br><span class="line"> self.filehandler = logging.handlers.RotatingFileHandler(self.filename,</span><br><span class="line"> self.mode, self.limit, self.backup_count)</span><br><span class="line"> <span class="keyword">else</span>: <span class="comment"># Use TimedRotatingFileHandler</span></span><br><span class="line"> self.filehandler = logging.handlers.TimedRotatingFileHandler(self.filename,</span><br><span class="line"> self.when, <span class="number">1</span>, self.backup_count)</span><br><span class="line"> self.filehandler.setLevel(self.filelevel)</span><br><span class="line"> formatter = logging.Formatter(self.filefmt, self.filedatefmt,)</span><br><span class="line"> self.filehandler.setFormatter(formatter)</span><br><span class="line"> self.logger.addHandler(self.filehandler)</span><br><span class="line"> </span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">set_logger</span><span class="params">(self, **kwargs)</span>:</span></span><br><span class="line"> <span class="string">'''Configure the logger.'''</span></span><br><span class="line"> keys = [<span class="string">'mode'</span>,<span class="string">'cmdlevel'</span>,<span class="string">'filelevel'</span>,<span class="string">'filefmt'</span>,<span class="string">'cmdfmt'</span>,\</span><br><span class="line"> <span class="string">'filedatefmt'</span>,<span class="string">'cmddatefmt'</span>,<span class="string">'backup_count'</span>,<span class="string">'limit'</span>,\</span><br><span class="line"> <span class="string">'when'</span>,<span class="string">'colorful'</span>]</span><br><span class="line"> <span class="keyword">for</span> (key, value) <span class="keyword">in</span> kwargs.items():</span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">not</span> (key <span class="keyword">in</span> keys):</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">False</span></span><br><span class="line"> setattr(self, key, value)</span><br><span class="line"> <span class="keyword">if</span> isinstance(self.cmdlevel, str):</span><br><span class="line"> self.cmdlevel = getattr(logging, self.cmdlevel.upper(), logging.DEBUG)</span><br><span class="line"> <span class="keyword">if</span> isinstance(self.filelevel, str):</span><br><span class="line"> self.filelevel = getattr(logging, self.filelevel.upper(), logging.DEBUG)</span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">not</span> <span class="string">"cmdfmt"</span> <span class="keyword">in</span> kwargs:</span><br><span class="line"> self.filefmt=<span class="string">'[%(asctime)s] %(filename)s line:%(lineno)d %(levelname)-8s%(message)s'</span></span><br><span class="line"> self.filedatefmt = <span class="string">'%Y-%m-%d %H:%M:%S'</span></span><br><span class="line"> self.cmdfmt=<span class="string">'[%(asctime)s] %(filename)s line:%(lineno)d %(levelname)-8s%(message)s'</span></span><br><span class="line"> self.cmddatefmt = <span class="string">'%H:%M:%S'</span></span><br><span class="line"> <span class="keyword">if</span> self.cmdlevel > <span class="number">10</span>:</span><br><span class="line"> self.filefmt = <span class="string">'[%(asctime)s] %(levelname)-8s%(message)s'</span></span><br><span class="line"> self.cmdfmt = <span class="string">'[%(asctime)s] %(levelname)-8s%(message)s'</span></span><br><span class="line"> self.cmddatefmt = <span class="string">'%Y-%m-%d %H:%M:%S'</span></span><br><span class="line"> self.init_logger()</span><br><span class="line"> self.add_streamhandler()</span><br><span class="line"> self.add_filehandler()</span><br><span class="line"> <span class="comment"># Import the common log functions for convenient</span></span><br><span class="line"> self.import_log_funcs()</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">True</span></span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">import_log_funcs</span><span class="params">(self)</span>:</span></span><br><span class="line"> <span class="string">'''Import the common log functions from the logger to the class'''</span></span><br><span class="line"> log_funcs = [<span class="string">'debug'</span>, <span class="string">'info'</span>, <span class="string">'warning'</span>, <span class="string">'error'</span>, <span class="string">'critical'</span>,</span><br><span class="line"> <span class="string">'exception'</span>]</span><br><span class="line"> <span class="keyword">for</span> func_name <span class="keyword">in</span> log_funcs:</span><br><span class="line"> func = getattr(self.logger, func_name)</span><br><span class="line"> setattr(self, func_name, func)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">trace</span><span class="params">(self)</span>:</span></span><br><span class="line"> info = sys.exc_info()</span><br><span class="line"> <span class="keyword">for</span> file, lineno, function, text <span class="keyword">in</span> traceback.extract_tb(info[<span class="number">2</span>]):</span><br><span class="line"> self.error(<span class="string">'%s line:%s in %s:%s'</span> % (file, lineno, function, text))</span><br><span class="line"> self.error(<span class="string">'%s: %s'</span> % info[:<span class="number">2</span>])</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line"> log = Log(cmdlevel=<span class="string">'info'</span>)</span><br><span class="line"> <span class="comment"># log = Log(cmdlevel='debug')</span></span><br><span class="line"> log.set_logger(cmdlevel=<span class="string">'debug'</span>)</span><br><span class="line"> log.debug(<span class="string">'debug'</span>)</span><br><span class="line"> log.info(<span class="string">'debug%s'</span> % <span class="string">'haha'</span>)</span><br><span class="line"> log.error((<span class="number">1</span>,<span class="number">2</span>))</span><br><span class="line"> log.error(<span class="string">'debug'</span>)</span><br><span class="line"> log.info({<span class="string">'a'</span>:<span class="number">1</span>,<span class="string">'b'</span>:<span class="number">2</span>})</span><br><span class="line"> os.system(<span class="string">"pause"</span>)</span><br><span class="line"> <span class="class"><span class="keyword">class</span> <span class="title">A</span><span class="params">()</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, log)</span>:</span></span><br><span class="line"> self.log = log</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">a</span><span class="params">(self,a)</span>:</span></span><br><span class="line"> self.log.info(a)</span><br><span class="line"> <span class="class"><span class="keyword">class</span> <span class="title">B</span><span class="params">()</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, log)</span>:</span></span><br><span class="line"> self.log = log</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">b</span><span class="params">(self,a)</span>:</span></span><br><span class="line"> self.log.info(a)</span><br><span class="line"> a = A(log)</span><br><span class="line"> a.a(<span class="string">"test a"</span>)</span><br><span class="line"> b = B(log)</span><br><span class="line"> b.b(<span class="number">5</span>)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">fun</span><span class="params">(a)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">10</span>/a</span><br><span class="line"> <span class="keyword">try</span>:</span><br><span class="line"> a = fun(<span class="number">0</span>)</span><br><span class="line"> <span class="keyword">except</span>:</span><br><span class="line"> log.trace()</span><br></pre></td></tr></table></figure>
<h2 id="例子">例子</h2><p>用的时候把log.py丢到工程目录然后import进来初始化一个Log对象即可。</p>
<p>如果全部使用默认配置(具体值请看Log类的init函数):<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># tmp.py</span></span><br><span class="line"><span class="keyword">import</span> log</span><br><span class="line">log = log.Log()</span><br><span class="line">log.debug(<span class="string">'hello, world'</span>)</span><br><span class="line">log.info(<span class="string">'hello, world'</span>)</span><br><span class="line">log.error(<span class="string">'hello, world'</span>)</span><br><span class="line">log.critical(<span class="string">'hello, world'</span>)</span><br></pre></td></tr></table></figure></p>
<p>得到结果:<br>在命令行跟文件里面分别记录运行日志,命令行呈现大于DEBUG级别的记录,文件记录大于INFO级别的记录。文件名跟主程序的py名字一样,这里是<code>tmp.log</code>。里面内容:<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">[<span class="number">2016</span>-<span class="number">05</span>-<span class="number">29</span> <span class="number">17</span>:<span class="number">17</span>:<span class="number">05</span>] tmp.py line:<span class="number">6</span> INFO hello, world</span><br><span class="line">[<span class="number">2016</span>-<span class="number">05</span>-<span class="number">29</span> <span class="number">17</span>:<span class="number">17</span>:<span class="number">05</span>] tmp.py line:<span class="number">7</span> ERROR hello, world</span><br><span class="line">[<span class="number">2016</span>-<span class="number">05</span>-<span class="number">29</span> <span class="number">17</span>:<span class="number">17</span>:<span class="number">05</span>] tmp.py line:<span class="number">8</span> CRITICALhello, world</span><br><span class="line">[<span class="number">2016</span>-<span class="number">05</span>-<span class="number">29</span> <span class="number">17</span>:<span class="number">17</span>:<span class="number">49</span>] tmp.py line:<span class="number">6</span> INFO hello, world</span><br><span class="line">[<span class="number">2016</span>-<span class="number">05</span>-<span class="number">29</span> <span class="number">17</span>:<span class="number">17</span>:<span class="number">49</span>] tmp.py line:<span class="number">7</span> ERROR hello, world</span><br><span class="line">[<span class="number">2016</span>-<span class="number">05</span>-<span class="number">29</span> <span class="number">17</span>:<span class="number">17</span>:<span class="number">49</span>] tmp.py line:<span class="number">8</span> CRITICALhello, world</span><br></pre></td></tr></table></figure></p>
<p>cmd显示运行结果:<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">[<span class="number">17</span>:<span class="number">17</span>:<span class="number">05</span>] tmp.py line:<span class="number">5</span> DEBUG hello, world</span><br><span class="line">[<span class="number">17</span>:<span class="number">17</span>:<span class="number">05</span>] tmp.py line:<span class="number">6</span> INFO hello, world</span><br><span class="line">[<span class="number">17</span>:<span class="number">17</span>:<span class="number">05</span>] tmp.py line:<span class="number">7</span> ERROR hello, world</span><br><span class="line">[<span class="number">17</span>:<span class="number">17</span>:<span class="number">05</span>] tmp.py line:<span class="number">8</span> CRITICALhello, world</span><br><span class="line">Hit any key to close this window...</span><br></pre></td></tr></table></figure></p>
<p>里面的内容符合对文件跟cmd的level级别筛选规则,显示的格式也分别符合<code>Log类</code>init默认初始化参数的formatter设置的规则。</p>
<p>如果要更改设置,直接调用<code>log.set_logger</code>就可以了。一般来说很少会有更改设置的情况,都是直接初始化就一直用到结束。有一种情况就是给出一个可以调整log level的级别的配置接口。这样程序运行的过程中,遇到bug用户可以调整日志级别,然后把debug日志记录获取到发给开发人员分析。</p>
<p>另外,封装的log.py比原来的logging模块多了一个trace接口。可以打印exception的详细信息。具体用法可以看封装的文件里边的例子。</p>
<h2 id="其他">其他</h2><h3 id="1-_formatter配置">1. formatter配置</h3><p>下面是formatter用到的匹配规则,其中asctime还可以进一步配置:命令行通过<code>cmddatefmt</code>、文件日志通过<code>filedatefmt</code>,具体写法可参照Log类的初始化函数。<br><figure class="highlight gherkin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">+---------------------+-----------------------------------------------------------------------------</span><br><span class="line">|<span class="string"> %(name)s </span>|<span class="string"> Logger的名字 </span><br><span class="line"></span>|<span class="string"> %(levelno)s </span>|<span class="string"> 数字形式的日志级别 </span><br><span class="line"></span>|<span class="string"> %(levelname)s </span>|<span class="string"> 文本形式的日志级别 </span><br><span class="line"></span>|<span class="string"> %(pathname)s </span>|<span class="string"> 调用日志输出函数的模块的完整路径名,可能没有 </span><br><span class="line"></span>|<span class="string"> %(filename)s </span>|<span class="string"> 调用日志输出函数的模块的文件名 </span><br><span class="line"></span>|<span class="string"> %(module)s </span>|<span class="string"> 调用日志输出函数的模块名 </span><br><span class="line"></span>|<span class="string"> %(funcName)s </span>|<span class="string"> 调用日志输出函数的函数名 </span><br><span class="line"></span>|<span class="string"> %(lineno)d </span>|<span class="string"> 调用日志输出函数的语句所在的代码行 </span><br><span class="line"></span>|<span class="string"> %(created)f </span>|<span class="string"> 当前时间,用UNIX标准的表示时间的浮 点数表示 </span><br><span class="line"></span>|<span class="string"> %(relativeCreated)d </span>|<span class="string"> 输出日志信息时的,自Logger创建以 来的毫秒数 </span><br><span class="line"></span>|<span class="string"> %(asctime)s </span>|<span class="string"> 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒</span><br><span class="line"></span>|<span class="string"> %(thread)d </span>|<span class="string"> 线程ID。可能没有 </span><br><span class="line"></span>|<span class="string"> %(threadName)s </span>|<span class="string"> 线程名。可能没有 </span><br><span class="line"></span>|<span class="string"> %(process)d </span>|<span class="string"> 进程ID。可能没有 </span><br><span class="line"></span>|<span class="string"> %(message)s </span>|<span class="string"> 用户输出的消息 </span><br><span class="line">+---------------------+-----------------------------------------------------------------------------</span></span><br></pre></td></tr></table></figure></p>
<h3 id="2-_Use_set_logger_to_change_settings">2. Use set_logger to change settings</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Change limit size in bytes of default rotating action</span></span><br><span class="line">log.set_logger(limit = <span class="number">10240</span>) <span class="comment"># 10M</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Use time-rotated file handler, each day has a different log file, see</span></span><br><span class="line"><span class="comment"># logging.handlers.TimedRotatingFileHandler for more help about 'when'</span></span><br><span class="line">log.set_logger(when = <span class="string">'D'</span>, limit = <span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Use normal file handler (not rotated)</span></span><br><span class="line">log.set_logger(backup_count = <span class="number">0</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># File log level set to INFO, and stdout log level set to DEBUG</span></span><br><span class="line">log.set_logger(cmdlevel = <span class="string">'DEBUG'</span>, filelevel = <span class="string">'INFO'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Change default log file name and log mode</span></span><br><span class="line">log.set_logger(filename = <span class="string">'yyy.log'</span>, mode = <span class="string">'w'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Change default log formatter</span></span><br><span class="line">log.set_logger(cmdfmt = <span class="string">'[%(levelname)s] %(message)s'</span>)</span><br></pre></td></tr></table></figure>
</div>
<footer class="article-footer">
<!-- <a data-url="http://huangming.github.io/2016-05-29-python-log.html" data-id="cixmol31e001mewfu4hcuszrb" class="article-share-link">Share</a> -->
<nav id="article-nav">
<a href="/2016-05-31-python-excel.html" id="article-nav-newer" class="article-nav-link-wrap">
<!-- <strong class="article-nav-caption">Newer</strong> -->
<div class="article-nav-title">
«Python调用dll动态链接库操作excel
</div>
</a>
<a href="/2016-05-25-oracle-rebuild-temp-tablespace.html" id="article-nav-older" class="article-nav-link-wrap">
<!-- <strong class="article-nav-caption">Older</strong> -->
<div class="article-nav-title">Oracle收缩临时表空间»</div>
</a>
</nav>
<a href="http://huangming.github.io/2016-05-29-python-log.html#disqus_thread" class="article-comment-link">Comments</a>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/log/">log</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/python/">python</a></li></ul>
</footer>
</div>
</article>
<section id="comments">
<div id="disqus_thread">
<noscript>Please enable JavaScript to view the <a href="//disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
</div>
</section>
</section>
</div>
<footer id="footer">
<aside id="sidebar" class="outer">
<div class="widget-wrap">
<h3 class="widget-title">Categories</h3>
<div class="widget">
<ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/Vim/">Vim</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/blog/">blog</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/database/">database</a><span class="category-list-count">3</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/diary/">diary</a><span class="category-list-count">33</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/other/">other</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/python/">python</a><span class="category-list-count">3</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/vps/">vps</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/www/">www</a><span class="category-list-count">1</span></li></ul>
</div>
</div>
<div class="widget-wrap">
<h3 class="widget-title">Tags</h3>
<div class="widget">
<ul class="tag-list"><li class="tag-list-item"><a class="tag-list-link" href="/tags/backup/">backup</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/dokuwiki/">dokuwiki</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/excel/">excel</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/expdp/">expdp</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/hexo/">hexo</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/impdp/">impdp</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/linux/">linux</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/log/">log</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/markdown/">markdown</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/nginx/">nginx</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/oracle/">oracle</a><span class="tag-list-count">4</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/oracle热备/">oracle热备</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/python/">python</a><span class="tag-list-count">3</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/ssh/">ssh</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/vps/">vps</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/wiki/">wiki</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/云笔记/">云笔记</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/动态链接库/">动态链接库</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/正则/">正则</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/爬虫/">爬虫</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/自动化/">自动化</a><span class="tag-list-count">1</span></li></ul>
</div>
</div>
<div class="widget-wrap">
<h3 class="widget-title">Tag Cloud</h3>
<div class="widget tagcloud">
<a href="/tags/backup/" style="font-size: 10px;">backup</a> <a href="/tags/dokuwiki/" style="font-size: 10px;">dokuwiki</a> <a href="/tags/excel/" style="font-size: 10px;">excel</a> <a href="/tags/expdp/" style="font-size: 10px;">expdp</a> <a href="/tags/hexo/" style="font-size: 10px;">hexo</a> <a href="/tags/impdp/" style="font-size: 10px;">impdp</a> <a href="/tags/linux/" style="font-size: 10px;">linux</a> <a href="/tags/log/" style="font-size: 10px;">log</a> <a href="/tags/markdown/" style="font-size: 10px;">markdown</a> <a href="/tags/nginx/" style="font-size: 10px;">nginx</a> <a href="/tags/oracle/" style="font-size: 20px;">oracle</a> <a href="/tags/oracle热备/" style="font-size: 10px;">oracle热备</a> <a href="/tags/python/" style="font-size: 15px;">python</a> <a href="/tags/ssh/" style="font-size: 10px;">ssh</a> <a href="/tags/vps/" style="font-size: 10px;">vps</a> <a href="/tags/wiki/" style="font-size: 10px;">wiki</a> <a href="/tags/云笔记/" style="font-size: 10px;">云笔记</a> <a href="/tags/动态链接库/" style="font-size: 10px;">动态链接库</a> <a href="/tags/正则/" style="font-size: 10px;">正则</a> <a href="/tags/爬虫/" style="font-size: 10px;">爬虫</a> <a href="/tags/自动化/" style="font-size: 10px;">自动化</a>
</div>
</div>
<div class="widget-wrap">
<h3 class="widget-title">Recents</h3>
<div class="widget">
<ul>
<li>
<a href="/2016-12-27-oracle-ora00020.html">Oracle无法登陆:ORA-00020</a>
</li>
<li>
<a href="/2016-12-17-dokuwiki-nginx.html">Windows下用Nginx部署DokuWiki</a>
</li>
<li>
<a href="/2016-12-03-cloud-notes-2012.html">无意翻到当年的云笔记</a>
</li>
<li>
<a href="/2016-08-18-oracle-auto-backup-and-restore.html">oracle自动备份同步</a>
</li>
<li>
<a href="/2016-08-06-python-zhengze-pachong-qiubai.html">Python爬虫正则表达式抓取糗百笑话</a>
</li>
</ul>
</div>
</div>
</aside>
<div class="outer">
<div id="footer-info" class="inner">
© 2017 Mingo<br>
Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
</div>
</div>
</footer>
</div>
<nav id="mobile-nav">
<a href="/" class="mobile-nav-link">Home</a>
<a href="/archives" class="mobile-nav-link">Archives</a>
<a href="/vimwiki" class="mobile-nav-link">Wiki</a>
</nav>
<script>
var disqus_shortname = 'huangming';
var disqus_url = 'http://huangming.github.io/2016-05-29-python-log.html';
var disqus_config = function () {
this.page.url = PAGE_URL; // Replace PAGE_URL with your page's canonical URL variable
this.page.identifier = PAGE_IDENTIFIER; // Replace PAGE_IDENTIFIER with your page's unique identifier variable
};
(function() { // DON'T EDIT BELOW THIS LINE
var d = document, s = d.createElement('script');
s.src = '//'+disqus_shortname + '.disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
<!-- <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script> -->
<script src="/js/script.js" type="text/javascript"></script>
<script type="text/javascript">
var myDate = new Date()
var m = myDate.getMinutes()
m = m % 10
document.body.style.background = '#333 url("/css/images/bgr'+m+'.jpg") top left'
document.getElementById('wrap').style.background='#333 url("/css/images/bgr'+m+'.jpg") top left'
</script>
</div>
<div id="spig" class="spig">
<div id="message">正在加载中……</div>
<div id="mumu" class="mumu"></div>
</div>
</body>
</html>