尝试使用Python的日志模块

作为一个程序猿(programmer),程序日志本应是和单元测试同等重要的。但是,由于平时的编码任务都是一个人做,所以没有觉得程序日志很重要。直到工作中需要使用陌生人编写的代码,而且代码质量很烂……

于是我被迫学了怎么使用Python的Logging模块……

以下就是对日志模块的简单应用:

  • DEBUG级别以上的日志,输出到控制台
  • INFO级别以上的日志,输出到dev.log文件
  • ERROR级别以上的日志,还输出到error.log文件
  • CRITICAL级别以上的日志,还输出到critical.log文件,并且日志格式与其他的不同,重在将引发错误的原因记录下来。

把这个文件当做模块引入之后,只需要使用LOGGER的相关函数代替print就行了。可根据需要修改这些.log的文件名。

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
# minori_log.py - 日志
# - 使用方法
# from minori_log import logger as LOGGER
# LOGGER.debug("")
# LOGGER.info("")
# LOGGER.warning("")
# LOGGER.exception("")
# LOGGER.error("")
# LOGGER.critical("")


# https://docs.python.org/3/howto/logging.html#basic-logging-tutorial
# - CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET
# - print() 平常的输出
# - logging.info() 为了诊断问题而详细记录
# - warning.warn() 可避免的错误,应当消除的错误
# - logging.warning 程序无法处理这种情形,但是应当记录此事件
# - raise Exception("??") 报告一个关于特定的运行时事件的错误
# - logging.error(), logging.exception, logging.critical() 报告未抛出异常而抑制了此错误

import os
from datetime import datetime, date
import logging # 日志


# 可以根据需要自主修改的部分
_FILENAME_BASE = "log"
# end

path = ""
if not os.path.exists('log'): # or os.path.isdir('log'):
# log作为文件或文件夹都不存在
os.mkdir('log')
path = 'log'
elif os.path.isdir('log'):
# log是文件夹
path = 'log'
else:
# log是文件
pass


# 文件是不是当天创建的
# - 需确保文件存在,再调用
def is_created_today(filename):
# 今天
date_today = date.today()
file_created_date = datetime.fromtimestamp(os.path.getctime(filename)).date()
if not date_today == file_created_date:
return False

return True


# 文件的创建日期的字符串表示
def get_file_created_date_str(filename):
return str(datetime.fromtimestamp(os.path.getctime(filename)).date())


# 如果文件或文件夹不是今天创建的,则改名
# - 需确保文件或文件夹不存在
def rename_if_not_created_today(filename, new_name):
created_today = is_created_today(filename)
filesize = os.path.getsize(filename)
if 0 == filesize and not created_today:
# 如果文件尺寸是0,且不是今天创建的,则删除掉
os.unlink(filename)
elif not created_today:
# 如果不是今天创建的,则改名
os.rename(filename, new_name)
else:
pass


# 创建日志记录器
logger = logging.getLogger("minori")
logger.setLevel(logging.DEBUG)


# console handler
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)
# - 格式化器
consoleh_formatter = logging.Formatter(
# 格式:时间 日志级别 日志消息 文件路径(line 行号)
"%(asctime)s %(levelname)-8s %(message)-80s %(pathname)s(line %(lineno)d)")
# - 设置格式化器
console_handler.setFormatter(consoleh_formatter)
# - 添加handler
logger.addHandler(console_handler)


# info-handler
infoh_filename = os.path.join(path, "{base}.log".format(base=_FILENAME_BASE))
# 处理旧的日志文件
# - 如果文件存在,且不是目录,且不是今天创建的
if os.path.exists(infoh_filename): # and not os.path.isdir(infoh_filename):
infoh_archive_filename = os.path.join(path, "{base}-{yyyy_mm_dd}.log".format(
base=_FILENAME_BASE,
yyyy_mm_dd=get_file_created_date_str(infoh_filename))
)
rename_if_not_created_today(infoh_filename, infoh_archive_filename)

info_handler = logging.FileHandler(filename=infoh_filename, encoding="utf-8")
# 日志级别
info_handler.setLevel(logging.INFO)
# 日志格式
infoh_formatter = consoleh_formatter
info_handler.setFormatter(infoh_formatter)
logger.addHandler(info_handler)


# error-handler
errorh_filename = os.path.join(
path, "{base}-error.log".format(base=_FILENAME_BASE))
# 处理旧的日志文件
if os.path.exists(errorh_filename):
errorh_archive_filename = os.path.join(path, "{base}-error-{yyyy_mm_dd}.log".format(
base=_FILENAME_BASE,
yyyy_mm_dd=get_file_created_date_str(errorh_filename))
)
rename_if_not_created_today(errorh_filename, errorh_archive_filename)

error_handler = logging.FileHandler(filename=errorh_filename, encoding="utf-8")
# 日志级别
error_handler.setLevel(logging.ERROR)
# 日志格式
errorh_formatter = consoleh_formatter
error_handler.setFormatter(errorh_formatter)
logger.addHandler(error_handler)


# critical-handler
criticalh_filename = os.path.join(
path, "{base}-critical.log".format(base=_FILENAME_BASE))
# 处理旧的日志文件
if os.path.exists(criticalh_filename):
criticalh_archive_filename = os.path.join(path, "{base}-critical-{yyyy_mm_dd}.log".format(
base=_FILENAME_BASE,
yyyy_mm_dd=get_file_created_date_str(criticalh_filename)
))
rename_if_not_created_today(criticalh_filename, criticalh_archive_filename)

critical_handler = logging.FileHandler(filename=criticalh_filename,encoding="utf-8")
# 日志格式
critical_handler.setLevel(logging.CRITICAL)
# 日志格式
criticalh_formatter = logging.Formatter(
# 格式:时间 日志级别 文件路径(line 行号) 日志消息
"%(asctime)s %(levelname)-8s %(pathname)s(line %(lineno)d)\n%(message)s")
critical_handler.setFormatter(criticalh_formatter)
logger.addHandler(critical_handler)

从Notion迁移到Github看板

Notion作为一款笔记类的软件或者APP,在首页的口号是:

1
2
Write, plan, collaborate, and get organized. Notion is all you need — in one tool.
编写、计划、协作、整理。只需一个工具——Notion——即可满足您的所有需求。

它的的四大用途——Notes, DocsKnowledge BaseTasks, ProjectsDatabases,除了Tasks, Projects之外,我都可以用Evernote做到。
于是使用了Notion几次后,发现自己只用它当任务看板……直到发现GitHub看板可以代替Notion的Tasks, Projects

GitHub的看板的创建和使用都像创建代码库一样简单,可以设为公开的或私人的。而且每天都需要用GitHub也就意味着不需要额外注册一个账号。于是Notion被我抛弃了。

最近,对外国人和台湾人的看法变得负面了

电影《流浪地球》

自从在贴吧见识过漫画《蝙蝠侠》的失智漫迷后,我对蝙蝠侠中强行没有超能力的设定就敬而远之了,继而渐渐地不喜欢美国的超级英雄。可是一直没有找到令自己信服的理由。自从去电影院看过《流浪地球》,终于找到了其中的缘由。

美国的超级英雄电影,最近的套路过于老套,都是“数个美国的超级英雄,靠超能力打败各种有黑科技的外星人、神明之类的敌人,拯救了美国,顺便拯救了世界”。

《流浪地球》的立意,从一开始就比美国的超级英雄高出一截,“全世界的人联合起来,拯救我们赖以生存的地球”。是的,这里没有美国,有的是全球的人。这里的人不是全部说英语的人,他们说自己的语言,有AI(人工智能)为他们做同声传译。

The Internationale

  • 从来就没有什么救世主(Il n'est pas de sauveurs suprêmes)
  • 也不靠神仙皇帝!(Ni Dieu, ni César, ni tribun)
  • 要创造人类的幸福(Producteurs, sauvons-nous nous-mêmes)
  • 全靠我们自己!(Décrétons le salut commun)

以下段落不适合以下人群阅读:台独、白皮猪、香蕉人

Read More

修改hosts文件,屏蔽百度百家号

中国一家独大的搜索引擎“百度”,已经肆无忌惮地把搜索结果首屏的流量引向自家的平台了。有一篇《搜索引擎百度已死》总结了这种现象。

那么,作为一般用户,通过修改hosts把抄袭和谣言占多数的百度百家号间接屏蔽,避免自己误入这些网址吧。

Windows 10为例,使用管理员权限启动notepad一类的文字处理程序,打开这个文件C:\Windows\System32\drivers\etc\hosts
,在hosts文件末尾新建一个空行,复制下面的代码,并保存:

1
2
3
# 屏蔽百家号
127.0.0.1 baijiahao.baidu.com
::1 baijiahao.baidu.com

以后再误入百家号的网址时,网页浏览器会因为无法连接服务器而报连接失败。

新的插件Hexo-helper-link-too发布了

由于Hexo官方的link_to不能指定<a>链接的title,因此将整个Hexo库复制下来,删除了非必需的文件后,修改代码,产生了一个山寨link_tolink_too

与官方link_to的差别,除了可能存在的BUG,特性方面的变更只有可以在options里指定title。未指定titletext会作为title

插件名为hexo-helper-link-too,已经发布在NPM,代码托管在GitHub
又是一个只有我自己用的插件?233

修改Landscape的主题配置

Hexo默认的主题是Landscape,很多默认的设置都无法满足需求,然而尝试过Next发现Next也不省心,干脆自己动手改造Landscape吧!

首先定位Landscape主题的_config.yml文件,在theme/landscape/_config.yml

如果没有进行深度魔改,值得修改之处有2点。menufavicon

比如首先用

1
$ hexo new page about

增加about页面,然后在_config.ymlmenu段落中增加:

1
2
关于我: /about
'@issiki': 'https://github.com/issiki'

# Miscellaneous下方的favicon则对应source目录下的favicon.png,在该处放置名为favicon.png的适合做favicon的图像即可。

为hexo博客添加404页面

source目录下新建一个404.md,在文件头部添加以下几行

1
2
3
---
title: 404
---

之后的内容按照普通Markdown语法为所欲为即可。

之后按正常的发布步骤,生成博文并运行本地服务器

1
$ hexo generate && hexo server

检查
http://localhost:4000/404.html
的格式。检查无误之后发布

1
$ hexo deploy

最后是在线检查,访问一个不存在的URL看看是否成功自定义404页面

动画《夏目友人帐第一季》

(ねこ)友人帳(ゆうじんちょう)

夏目看得见妖怪,别人看不见。 夏目的祖母玲子也看得见,因为奇怪的举动被孤立。玲子打败妖怪后让妖怪把名字写在纸上。友人帐即是这些写有妖怪名字的纸张装订而成。玲子的灵力似乎过于强大,破坏这些纸张能伤害甚至杀死妖怪。那么玲子知道这一点吗?写作“友人帐”,读作“生死簿”?

猫老师的声音……

妖怪等了玲子一辈子……

感觉玲子始乱终弃……

露神(つゆかみ)(ほこら)

单相思的妖怪。不知道有没有保佑当地。信徒越来越少,是因为不灵,还是因为新生代不信了呢?

吃剩饭又洗碗的妖怪。

八ツ原の怪人

又是寂寞的妖怪,伪装成大姐姐接近夏目。

有高强法力的僧人居然是胡乱放地图炮……

找到能互相理解的人真的很幸运。

时雨と少女

心色の切符

水底の燕

子狐とぼうし

儚い光

あやかし祓い

アサギの琴

ニャンコ徒然帐

五日印

秋の夜宴