Python的字符串编码

Python2的编码

在Python2中,str和unicode都是basestring的子类。

str是unicode经过编码后的字节组成的序列。

utf-8编码的str是可变长度,节省空间。unicode占固定长度字节,浪费空间。所以网络传输或者保存文件通常会使用unf-8.

下面这段代码,展示了str和unicode的关系。

要注意的是,要处理字符串,需要尽量保证要么都是str,要么都是unicode。否则可能会遇到编码错误,比如下面这样。

上面的代码就是试图用unicode格式化str,是一般pythoner都会遇到的错误。

可以看出,如果包含中文,又不只包含中文,就会打印出中文的编码。一种可选的处理方式是,用正则表达式替换出unicode编码的内容。

Python3的编码

Python3中,字符串是以unicode编码的,就没有str和unicode了,只有str,用unicode编码。

用unicode表示的str,通过encode()方法可以编码为bytes。网络传输或文件保存使用bytes,节省空间。byte可以通过decode方法转换成unicode。

建议使用uft-8进行转换。注意,str和bytes是python的对象,utf-8是编码方式。

建议在开头添加这样的编码声明:

实际上Python只检查#、coding和编码字符串,其他的字符都是为了美观加上的。这段代码是告诉Python解释器,对于这个文件采用什么样的编码方式。如果没有这一行,就会默认为ASCII,遇到汉字会无法解析。

在Pycon2012上有个名为Unicode之痛的演讲,讲的比较仔细。演讲中提出五个事实以及处理Unicode的三个建议:

我们有五个不可忽视的事实:

  1. 程序中所有的输入和输出均为 byte
  2. 世界上的文本需要比 256 更多的符号来表现
  3. 你的程序必须处理 byte 和 unicode
  4. byte 流中不会包含编码信息
  5. 指明的编码有可能是错误的

这是你在编程中保持 Unicode 清洁的三个建议:

  1. Unicode 三明治:尽可能的让你程序处理的文本都为 Unicode 。
  2. 了解你的字符串。你应该知道你的程序中,哪些是 unicode, 哪些是 byte, 对于这些 byte 串,你应该知道,他们的编码是什么。
  3. 测试 Unicode 支持。使用一些奇怪的符号来测试你是否已经做到了以上几点。

Pycon 20142015中都提到过Unicode,有兴趣可以看一下这两个视频演讲。

参考资料

  1. Python字符编码详解
  2. 廖雪峰:字符串和编码
  3. Python 字符编码判断
  4. Python如何输出包含在对象中的中文字符?
  5. 由__future__中unicode_literals引起的错误来研究python中的编码问题

 

 

Ubuntu终端和Vim使用Solarized配色

Solarzed是我最喜欢的配色,这个配色最大的好处就是全平台。无论是Item2,bash,Vim还是Tmux,都一应俱全。可以在所有的工具上都达到统一。

在Vim中更改配色非常简单,只要下载好solarized.vim,然后在~/.vim中创建一个colors文件夹复制进去,就好了。然后在.vimrc中做如下配置,就可以使用。

但是在ubuntu中,这样配置好了之后,打开vim,会发现vim里面是灰蒙蒙的一片。这是因为终端的配色方案还没有修改,按照一下的步骤将终端的配色方案也更改为Solarized,就好了。

修改方式如下。

1.设置dircolors

其中第二行你可以选择自己喜欢的颜色,不一定非得是256.第三行的.dircolors应该是你自己的路径。

2.设置终端配色

这样,Vim和终端的颜色都设置好了。

参考资料:

  1. http://luodw.cc/2015/10/06/vimcolor/
  2. https://github.com/seebi/dircolors-solarized#installation
  3. https://github.com/seebi/tmux-colors-solarized

 

 

滑雪记

新年结束回来那天是周六,公司决定周六周日都上班,加上接下来的六天(我司六天工作制),我已经连续工作八天了Orz,还伴随着加班。今天终于可以休息了,去绍兴乔波滑雪场浪了一天。

车是17座的中巴,司机老余说这车后座不行,靠背直接是直的,因为这车不能超过6米,就按照5.99米做的。亿维客也是这样的,所以后座特别难受。而且后座为了能在下面塞行李,还给加高了Orz!这是我坐过最难坐的座位了,而且我上次坐这车也是最后面,衰。

虽然早知道是个室内的滑雪场,但是实际看到之后还是稍微有些失望。本以为会和电视里面那样很长,雪很白,有大大的弯道……结果进去之后是这样子的。

后来滑起来,发现这并不重要。赛道再长,也是得扛着滑雪板上去……用到的也就那么一块。真正有关系的就是这雪下面是冰,太滑了,这缺点很严重。把滑雪板扛上去,一只脚踩上,抬另一只脚的时候,你就会滑下去或者滑倒。

所以要把滑雪板横着放,脚踩上去,再转过来。这也是个技术活,有可能没准备好,人已经开始滑了。

上图左边是练习的场地,用户要自己扛滑雪板上去,哼哧哼哧,两秒滑下来,爽完。再爬上去。就这么上去两趟,我就想回家了。

好在中间有“魔毯”,就是电梯,上面防滑,踩着滑板上去,电梯把你送到顶,从右边滑下来。

但是上这个魔毯有个条件,要经过场地里面教练的考试,考过了才能上。考试的内容是从练习场顶端直线滑下来,滑到一半的时候刹住。我后来发现这考试是很有必要的!因为这个考试我才真正掌握了内八字刹车。在这方面我发挥了自己考驾照的天赋,一次性通过。上了魔毯,简直是发现另一个世界的大门,好高啊,这才爽啊!运用我的刹车技巧,想快便快,想慢便慢。下来之后还能潇洒的做一个拐弯!顿时觉得自己掌握了滑雪的精髓。有点不想做程序员了,做滑雪运动员。

之后就根本不想回家了。上魔毯,嗖嗖嗖滑下来,再上去,不亦乐乎。缺点就是我觉得魔毯太慢了,虽然不用自己爬,也还是慢。我觉得可以设计成这种:

两边分别是两个相对的坡,从右边滑倒左边,左边垂直电梯上到顶,再从左边滑倒右边。这样就可以一直爽了。不知道有没有滑雪场设计成这样。我觉得自己不仅有滑雪天赋,可能还有建造滑雪场的天赋。做一个程序员很可能给人类的发展造成阻碍了。

说说摔倒。我玩过旱冰,冰刀,VR滑雪。都是摔倒级别的水平,这里面感觉最疼的是旱冰,冰刀这种,重心容易落在后面,摔倒就想用手扶,手会很疼。最不疼的当然是VR滑雪了,呵呵。谈谈真实的滑雪吧,我发现摔倒了一点都不疼!地上都是雪,穿的又厚。有个技巧就是一定要向侧边摔倒,别压着手,肯定没事,滑雪板那么长前后摔难度也挺大的……发现这一点之后,我疯狂地摔倒,进步很快,上了魔毯就再没摔过了。

今天一起去玩的同事小野晚上告诉我说他已经辞职了,有点伤感,放两张自拍吧。希望不会吓到大家。

明天开始又要写代码了,加油!

 

Django的日志配置

Django对于日志输出的信息是很完善的,request的信息,setting配置,trackback的信息,一应俱全,足够我们调试了。但是在线上环境,如果让用户看到这些信息,是很不安全的(暴露代码)。所以在线上我们要关闭Debug,但是又不能扔掉这些调试信息,这就要用到logging模块。

logging模块其实是Python的模块,在Django中有很多本地化的支持。

理解Logger

首先要理解logging的工作,这里面主要有四个东西:格式器formatter,过滤器filter,处理器handler,日志实例logger。

处理流程是这样的。首先,在代码中。我们拿到的是logger实例,通过这个实例来记录信息。

然后,名字是django的这个logger就会把信息交给相应的handler,handler把信息用formater和filter处理一下,提交log(保存到文件,数据库,或者发送邮件)。

一般来说,handler可以是send_email,error_file等负责处理的方式,在logger中可以重复使用handler。例如我们的django处理器使用了send_email, error_file 这两个处理器,request处理器使用error_file,info_file两个处理器,logger和handler可以理解成多对多的关系,嘻嘻。

配置方式

Python中可以使用多种格式配置logging,比如.conf, .ini等。

在Django中,我们是把有关logging的配置写到settings里面。相应的配置及解释如下(仅供参考)。

以上的配置文件中,有三个日志处理器。分别是:

  1. ‘django.request’:django的request发生error会自动记录,然后使用debug将信息记录到文件,还有mail_admins将信息通过邮件发送给管理员。这里邮件的功能非常棒!并不是一个纯文本信息,而是一个html文件,和我们在浏览器看到的错误页面一模一样!要正常使用邮件功能需要像我一样配置一下上面的邮件发件人信息。我是直接去网易申请了一个邮箱。要格外注意三点:1.一定要去邮件服务商开启SMTP服务;2.不同的邮件服务商可能有一些特殊的设置,比如网易,会给你一个客户端授权码,这个才是密码,而不是网页的登录密码。3 注意服务商有没有对发信频率的限制。
  2. ‘django’:使用console处理器,将信息输出。在开发的时候就可以使用这个处理器(什么?print? 太low了!)
  3. 最后一个处理器见注释。

最后,不要忘了给日志的路径响应的权限。比如Apache2服务器,就需要给www-data写权限:

参考资料

  1. python logging模块使用教程
  2. Django文档 – logging
  3. 我的网站搭建(第12天) 关闭调试
 

VimScript学习笔记(6):变量

既然VimScript可以作为一门编程语言,那么别人都有的变量、条件判断、循环,它也应该有。本文介绍这些内容。

变量

使用let为变量赋值。

从上面的代码也可以看出,VimScript是一个动态类型的编程语言。

如果使用set,那么就会作为一个选项(Option)赋值。取得Option的值需要在前面加一个&符号。

布尔类型有些特殊,是通过在前面no或者不加来区分。

由此也可以看出,Vim将0作为假,1零)作为真。

使用let&符号也可以为选项赋值。

区别在于,set只能赋一个单一的值,而let可以将它们作为变量来计算

如果要使用let设置Buffer-Local(只在当前窗口有效)的选项,要加l:前缀。同时打开两个文件,分别执行下面的代码。发现一个显示了行号,另一个没显示。

除了将选项作为变量,你还可以将寄存器作为变量。

输入下面的命令,然后移到切换到Normal Mode,键入"ap。你会发现Vim粘贴了寄存器a保存的内容。

寄存器的变量也可以被读出来:

其实,其他有很多地方都是用到了寄存器。例如使用yy复制一行,可以通过:echo @"查看,"就是一个匿名的寄存器。使用/someword搜索功能,可以使用:echo @/查看搜索的单词。

Vim中的变量有“名字空间”的概念,下面这个方式,会只设置当前窗口的hello变量。

通过:help internal-variables命令,可以查看Vim支持的所有的名字空间。

Numbers

VimScript支持两种数字类型,Numbers和Floats。

Number是32位的有符号整数。Float是单浮点数字类型。

Number类型支持不同的进制表示方法。0x0X开头的是16进制,0开头的是八进制。尝试以下代码。

因为019不是一个合法的八进制数,所以Vim会静默地将它当做10进制。这样并不安全,应该尽量不使用八进制。

Float类型支持科学表示方法。

如果涉及到NumberFloat的运算,Vim会将Number转换成Float,然后返回一个Float(类型提升)。

如果两个Number做除法,Vim会丢掉余数。(这几点和高级语言,如Python,的表现是一致的)

String

需要注意的是,+Number的运算符,而.才是用来连接字符串的。如果对字符串使用+,Vim会把字符串转换成数字。关于转换规则,我们在VimScript学习笔记(7):条件判断和比较这里讨论过了。

参考下面的运算。

要记住,String不能和Float一起处理,只能和Number进行处理。

特殊字符,使用\转义。

单引号包裹的,是纯字符串。不会进行转义。特殊的,连续两个单引号,被转义为一个单引号。

对一个编辑器的脚本语言来说,最重要的就是处理字符串了。在Vim中,内置了一些处理字符串的方法。例如,获取字符串的长度,分割,连接,处理大小写等等。具体的用法,参考下面的代码。