2013年9月29日星期日

批量改照片名为拍摄时间

去台北玩照的七百多张照片,是用手机和数码相机照的。摩托罗拉手机(Atrix 2)照的照片命名方式是YYYY-MM-DD_HH-MM-SS_XXX.jpg,例如2013-06-11_00-15-48_100.jpg,最后的100可能是指00:15:48秒的第100毫秒;而佳能相机(EOS 5D)照的照片命名方式是IMG_XXXX.JPG,例如IMG_5845.JPG。这些照片放到一个相册里面,按照名字排序后是混乱的,这让我在几百张照片里面很难快速找到某张照片。我用的相册软件(Picasa)不支持按拍摄时间排序,否则按照拍摄时间排序就可以了。

这么对比,才发现传统的数码相机给照片起名的方式有点蠢。我第一台数码相机是惠普的,前缀是hpim。索尼是DSC,莱卡是L,后面都跟着照片序列号。IMG_5845.JPG这样的名字没有任何有用的信息,而2013-06-11_00-15-48_100.jpg却给出了非常重要的照片元信息。在浏览相册时,看到名字就知道了这张照片是什么时候照的。

于是写了个批量改名的脚本,把佳能相机照的照片都改名为照片拍摄的时间。这样就能和手机照的照片放到一个相册里面,按名字排序,也就自然是按照拍摄时间排序了,浏览时候就很方便了。我觉得数码相机照的照片都可以这么处理,方便浏览,不过这要求数码相机的时间是准确的。

2013年9月25日星期三

MongoDB的高可用

一个应用的数据源是MongoDB,DBA已经配置了多机的Replication Set,但是在客户端程序用Pymongo连接的时候还指定的是一个IP。结果在网络升级的时候的网络瞬断,让MongoDB自动切换了master,导致客户端连接失败了,出现Master has changed的异常。其实早就计划要修改客户端配置,支持RS的,但是一直没有完成,终于掉进这个坑里面了。

有意思的是,如果MongoDB没有做RS,那么网络瞬断只会让服务短暂不可用,网络恢复的时候服务即可恢复;而服务端做了高可用,客户端没有进行相应的配置,可用性反而降低了。看来在服务端和客户端都进行正确配置的情况下才能实现真正的高可用性。

2013年9月17日星期二

性能比较

以下两个Python 3函数的性能差10倍。

def upgrade(url):
    """Upgrade HTTP URL to HTTPS URL."""
    components = urllib.parse.urlsplit(url)
    if components.scheme.lower() == 'http':
        return urllib.parse.urlunsplit(['https'] + list(components[1:5]))
    else:
        return url

def upgrade1(url):
    """Optimized version of upgrade, 10x faster."""
    if url[:5].lower() == 'http:':
        return 'https' + url[4:]
    else:
        return url

timeit分别测试100万次,耗时分别如下:
4.574674844741821
0.46399807929992676
什么时候用库函数,什么时候用基本的函数实现,需要综合考虑开发速度、灵活性和性能等因素。

2013年9月16日星期一

用Python进行HTTP基本认证

curl调用公司Jira需要基本认证(Basic access authentication)的REST API没有问题,但是用Python3的urllib.request按照文档操作,总是返回401

我怀疑是Jira的API需要某些特殊的header,我又用GitHub的API尝试,仍然返回401错误。我看到GitHub的API调用要求必须要有User-Agent,我以为urllib没有设UA,我又尝试设置UA,仍然是401。而实际上urllib是设置了UA的。

Google后发现不是urllib的问题,而是API服务器不遵守RFC的原因,原文在此urllib第一次发送不带验证信息的请求,在401之后会根据服务器响应的WWW-Authenticate头来进行BA。Jira的401是有这个头,可是返回的是Outh的challenge,所以BA也会失败:
WWW-Authenticate: OAuth realm="...snip..."
而GitHub的401完全没有这个头,没有遵守RFC 2616里面对这个头的"Must"要求。

解决办法是请求前就把Authorization头加上,这样直接进行BA,就可以规避服务器不返回正确WWW-Authenticate头的问题。