迁到丰台区

来北京已近六年,大小搬家经历了七八次,家当却是一次比一次多。实习和读书期间一直在海淀区晃悠。毕业以后在西二旗智学苑小住了3月,就因老婆来京工作地点交通不便搬到了曾经的宣武区牛街西里(现在属西城),北向一居开间,2k/月,暖气自付。

都说牛街是穆斯林聚居区,美食众多。我虽在牛街住了一年半,老北京小吃却没尝到多少,比如说豆汁、焦圈就没有试过。其中大部分原因是懒得尝试,还有对太油太腻的食物不太热衷。最让我留恋的食物只有两样:一个是老城伊的羊蝎子,另一个是聚宝源的肉饼。大伙烤肉的牛肉面本来也颇合我口味,但自从涨价五块钱以后,就不甚满意了。

本来计划在牛街居住两年或更久,也习惯了在那里的生活。后来因房东的卖房而打断,很多朋友可能对这种情况都深有体会且深恶痛绝。但好歹我遇到了一位实诚的房东,不仅少收了我一个月的租金,还补偿了我一笔违约金,也算是好聚好散。当初这个房子是在豆瓣上找到的,这让我的很多同事都比较惊讶。他们不知道文艺青年聚集的豆瓣还能交换此类生活信息,但我想,关于豆瓣他们不知道的事情可能还有很多 :)。

再次找房,考虑到我们俩的公司位置,还是打算在牛街附近找。但是这次尝试了一个新的途径,在小区内部贴条找房。谁知本来目标是本小区的房子,却租到了一个本小区业主在其它小区的房子。房子在丰台区右安门附近,临着二环,还是一居开间,西向,2.1k/月,包暖气。实话说,都是回迁小区,小区内部环境却比牛街西里差很多。但考虑到租房开支在生活支出里占大头,这个价格在周边也算便宜了,不能挑剔太多。

因为重新装修过没几年,房子内部的大体状况还算可以。唯一不好的是卫浴管道、设施比较陈旧,不少问题,我还没来得及修理。这种活我从来不愿意麻烦房东,自己就能干,省时省事。新家也不尽是坏处,附近交通上反而比牛街方便一些,在立交桥边公交线路多,也没那么堵。小区周边的小饭馆和超市也比牛街西里更多更近,尤其到晚上,临街小摊如同五道口一样兴盛。

看看房子,愈发能明白北京的区域发展不平衡。在房租房价上,南城要差北城一个档次,北城尤以西北房租、房价最高。大致原因应该是一方面西北是海淀区教育资源好,另一方面高校吸引高科技企业聚集,居民平均收入更高。我倒庆幸能在南城找房子,虽然上班路上得花费一个半小时,但好歹我老婆不用那么辛苦,且房租支出能不那么肉疼些。

今天本想骑我那尘封已久的公爵 600 出去转转来着,无奈天公不做美,只好补一补欠下来的近况。

PS: 今天是南京大学 110 年校庆,祝母校生日快乐!

Python JSON模块解码中文的BUG

很多语言或协议选择使用 ASCII 字符 “\”(backslash,0x5c) 作为字符串的转义符,包括 JSON 中的字符串。一般来说,使用 Python 中的 JSON 模块编码英文,不会存在转义符的问题。但如果使用 JSON 模块编解码中文,就可能面临着中文字符包含转义符带来的 bug。本篇文章给出了一个 badcase。

中文解码错误

测试用例文件里面包含繁体的“運動”二字,使用 GB18030 编码。使用 json 解码的错误如下:

$ cat decode.dat
{"a":"運動"}
$ python
>>> import json
>>> fp=open('decode.dat', 'r')
>>> json.load(fp, encoding='gb18030')
Traceback (most recent call last):
  File "", line 1, in 
  File "/home/yangwb/local/lib/python2.7/json/__init__.py", line 278, in load
    **kw)
  File "/home/yangwb/local/lib/python2.7/json/__init__.py", line 339, in loads
    return cls(encoding=encoding, **kw).decode(s)
  File "/home/yangwb/local/lib/python2.7/json/decoder.py", line 360, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/home/yangwb/local/lib/python2.7/json/decoder.py", line 376, in raw_decode
    obj, end = self.scan_once(s, idx)
UnicodeDecodeError: 'gb18030' codec can't decode byte 0xdf in position 0: incomplete
multibyte sequence

发生这个问题的原因,就存在于“運”字的编码之中。“運”的 GB18030 编码是 0xdf5c,由于第二个字符与转义符 “\” 编码相同,所以剩下的这个 0xdf 就被认为是一个 incomplete multibyte sequence。

我本来认为,既然已经提供了编码,json 模块就能够区分汉字与转义符(所以我觉得这应该是 json 的一个 bug)。但从实验来看,并非如此。对于一些不需提供字符编码的 JSON 解码器来说,我们倒可以用一种比较 tricky 的方法绕过上面这个问题,即在“運”字后面加一个额外的转义符:

{"a":"運\動"}

遗憾的是,这种方法对 Python 的 json 模块不适用。我仍不知道该如何解决这个解码问题。

中文编码——没错误!

对于相同的 case,Python 倒是能够编码成功:

$ cat in.dat
運動
$ python
>>> import json
>>> in_str = open('in.dat', 'r').read()
>>> out_f = open('out.dat', 'w', 0)
>>> dump_str = json.dumps({'a': in_str}, ensure_ascii=False, encoding='gb18030')
>>> out_f.write(dump_str.encode('gb18030'))
$ cat out.dat
{"a": "運動"}

所以这件事情就把我给搞糊涂了,Python 的 json 模块不能解码自己编码的 json 串。所以我觉得这可能是一个 bug,或者至少是 2.7.1 版本的 bug。

PS: 要仔细看文档

20120516:经网友 TreapDB 提醒,加载字符串时自己做 Unicode 转换,貌似能够解决这个问题。

$ cat decode.dat
{"a":"運動"}
$ python
>>> import json
>>> in_str = open('decode.dat', 'r').read().decode('gb18030')
>>> json.loads(in_str)

回头仔细看了一下 json 的文档,其中有这么一段:

Encodings that are not ASCII based (such as UCS-2) are not allowed, and should be wrapped with codecs.getreader(encoding)(fp), or simply decoded to a unicode object and passed to loads().

已经注明了 encoding 不支持非 ASCII-based 编码的参数,所以应该使用 getreader 进行转码,而不是让 json 模块去转码。看来是我没读懂文档,大惊小怪了,回家面壁去!

>>> json.load(codecs.getreader('gb18030')(fp))

WP Super Cache插件带来的500错误

今天博客服务器(Hostmonster 主机)全站从中午开始出现 500 错误,然后我登陆进 CPanel 各种查看日志、进程、数据库、PHP 状态,均未发现异常。后来又清理 php.ini、.htaccess,重启 PHP,也没有任何改善。只好给客服投了个 Ticket,准备等待客服解决。

后来灵机一动,发现同一主机 host 的其它 WordPress,有的活得很好,有的也是挂掉了。于是用排除法清理 wp-config.php,最终确定是 wp-config.php 中的 WP_CACHE 配置项有问题,删掉之后访问就恢复正常。

define('WP_CACHE', true); //Added by WP-Cache Manager

但由于 WP_CACHE 配置项是 WP Super Cache 自动增加的,一旦登陆进后台,WP Super Cache 就会自动把它再加上,后台页面又会出现 500 错误。于是乎我只好将整个 WP Super Cache 插件干掉(包括 wp-content 下的 php 脚本),终于一切恢复了正常。印象里删掉的 WP Super Cache 的版本是 0.9.9.*。

rm advanced-cache.php backup-*  cache/  wp-cache-config.php plugins/wp-super-cache/ -rf

考虑到 WP Super Cache 还是对性能有一定改善,又看了一下最新版的 WP Super Cache 是 1.0 版,我怀疑是 WP Super Cache 版本较旧造成的问题。虽然该版本已经使用了很长时间,不明白为什么今天才会爆出来 500 错误(也许 Hostmonster 主机程序进行了升级?),我还是装上了最新版本 WP Super Cache 插件。期望它不要再出现类似问题,否则只能弃用了。

既然我的博客不是同一主机上的个例,我想可能在 Hostmonster 上的其它主机也可能会遇到此类问题,特记录下来供参考。

警惕程序日志对性能的影响

做后台系统比做客户端软件的辛苦的地方,就是不能让程序轻易地挂掉。因为在生产环境中无法容易地复现或调试 bug,很多时候需要程序日志提供足够的信息,所以一个后台系统的程序员必须要明白该如何打日志(logging)。 很多语言都有自己现成的 logging 库,比如 Python 标准库中的 logging … Continue reading

64位Ubuntu上使用Network Connect

Network Connect 是 Juniper 公司出品的配合其安全硬件 VPN 解决方案的软件包,很多公司使用这个 VPN … Continue reading

修改exvim目录过滤逻辑为匹配拒绝

exVim 是一个非常优秀的 Vim 环境,通过它能够省去很多 Vim 插件的配置工作。自从使用上 exVim 后,我基本没有再自定义 … Continue reading

携友闲逛798

上周末正好有事到望京附近,顺便带老婆和朋友一起逛了逛 798 艺术中心,照了几张照片。我在里面逛得倒是依然自得,可惜同行的两位女同学兴致寥寥,于是没待太久就散了。

MIUI的贴心功能

预先声明:这不是一篇软文,我真的是出于对 MIUI 系统的喜爱才写的。 我的手机型号是华为 U8800,联通定制机,自带的 ROM 里太多乱七八糟的软件,后来就刷了华为官版的海外 ROM。这个 … Continue reading

上海流水

我上次去上海是 8 年前,记忆都已经模糊了,只剩下几个场景比较清晰。与吴诗涛坐在沪宁双层城际列车的楼梯间地板上享受列车空调,路过华东理工收费的小足球场和封闭的草坪足球场,以及在臭水沟边秦嘉诚宿舍里塞紧蚊帐捉蚊子。在豫园吃过什么已经忘了,只记得自动售货机的可乐很贵,地铁也很贵。逛南京路步行街的时候在下雨,走到外滩雨更大。在雨中仰望了一下金茂大厦和东方明珠电视塔,不记得那时有没有环球金融中心。 上周因公差有幸免费重游上海。之所以说有幸是因为互联网公司不比其它行业,即使是大公司,出差机会也很少。对于华为、宝洁这样的公司来说,恐怕不出差反而是有幸了。我也是第一次坐飞机——不要笑我。通过飞机相连,两个城市间的距离变得好小! 这次到上海的第一印象是厚厚的云层,以及落地前虹桥机场附近的繁华,飞机就好像贴着闹市区的头顶飞过,宾馆饭店的霓虹灯广告牌都清楚可辨。出了航站楼,就闻到一股久违了的江南的潮湿空气,更重要的是,空气中没有煤烟味。经过北京漫长的冬天,这种感觉给人的冲击感太强烈了。 第一天是在张江工作,所以住在了锦江之星的张江店。我厂的上海研发中心跟安捷伦在同一幢楼里,很不起眼。室内装修跟大厦、奎科没有什么太大不同,哦,跟奎科没有什么太大不同。跟奎科一样,会议室也比较容易预定。开了一天会,不提。 由于次日是周末,所以当天晚上就坐地铁 2 … Continue reading

妄谈时间序列表格型大数据系统设计

一直在特定领域的分布式系统一线摸爬滚打,曾取得一些微不足道的成绩,也犯过一些相当低级的错误。回头一看,每一个成绩和错误都是醉人的一课,让我在兴奋和懊恼的沉迷中成长。自己是个幸运儿,作为一个 freshman 就能够有机会承担许多 old guy 才能够有的职责。战战兢兢、如履薄冰的同时,在一线的实作和思考也让我获得了一些珍贵的经验,却直至今日才够胆量写出来一晒。这篇文章标题前面是“妄谈”两字,所持观点未必被所有人认可,我姑妄言之,有心之人姑听之。若有些友好的讨论,亦我所愿也。 我做的虽然也是分布式系统,却不够胆去讨论通用分布式系统的设计原则。因而这篇文章的主题限定到一个特定领域的分布式系统设计,这样即使别人有疑惑,我也可以把 TA … Continue reading

Page 1 of 5712345...102030...Last »