网络寻租

Programmer, Gamer, Hacker

Pyqt多国语言

| Comments

qt的多国语言支持方案

qt在设计的时候就考虑到了多国语言应该如何处理, 原理以及使用方法很简单. 如下:

第一步: 写代码的时候, 对于需要翻译的词语, 用tr()包起来, 比如:

QPushButton hello(QPushButton::tr("Hello world!"));

这样qt就知道这些词语是需要翻译的了. 然后qt需要把这些词语取出来, 放到一个文件里面去, 好进行下一步的翻译工作.

在你的pro文件里面说明这个文件的名称:

TRANSLATIONS    = clabel_zh_CN.ts

这样就可以利用lupdate这个工具来把需要翻译的词语取出来:

lupdate-qt4 clabel.pro

然后, 我们就可以开始翻译工作了. qt提供了一个配套的翻译工具: linguist:

linguist-qt4 clabel_zh_CN.ts

其实ts文件是xml的格式, 你想直接编辑文本也是可以的.

当做完翻译工作之后, 我们需要把ts文件编译一下, 方便程序使用:

lrelease-qt4 clabel_zh_CN.ts

这样就会生成clabel_zh_CN.qm. 最后, 在代码里面加上选择语言的代码:

QTranslator trans;
trans.load("clabel_zh_CN");
app.installTranslator(&trans);

QPushButton hello(QPushButton::tr("Hello world!"));
hello.show();

app.exec();

qt多国语言更详细的介绍在: http://doc.qt.nokia.com/4.6/i18n-source-translation.html

pyqt下面如何实现多国语言

pyqt里面实现的过程和qt里面的类似, 只是因为第一步需要扫描的不是c++代码, 所以需要利用一个pyqt的工具: pylupdate4, 用法和lupdate一样.

首先写程序

1
2
3
4
5
6
trans = QTranslator()
trans.load('plabel_zh_CN')
app.installTranslator(trans)

button = QPushButton(tr("hello world!"))
button.show()

等等, 里面的tr是什么?

def tr(msg):
    return QCoreApplication.translate("@default", msg)

qt翻译是根据类的名称来走的, 调用了什么类的tr, 就取这个类里面设置的翻译.

qt里面是可以利用QObject::tr来翻译, 但是pyqt里面不能, pylupdate4只是做字符串查找, 看有什么字符串是在tr后面的, 然后根据tr调用者来把这个词语归类, 如果没有调用者, 就把它归类到 “@default” 里面. 于是我就只好利用上面的方法来做一个规避..有点恶心, 看看以后是否会有更好的方法来处理.

对于类里面的翻译, 不需要那么麻烦:

class Input(QWidget):
    def __init__(self):
        super(Input, self).__init__()
        label = QLabel(self.tr("input:"))

这里面的tr, 就可以被正确翻译出来.

然后运行pylupdate, 因为我们是python程序, 没有pro, 就只能手动指定文件了

pylupdate4 main.py -ts plabel_zh_CN.ts

好了, 下面的步骤和c++的方法一样

linguist-qt4 clabel_zh_CN.ts
lrelease-qt4 plabel_zh_CN.ts

然后执行代码, 程序按照我们期望的方式翻译过来了, 是不是很简单?

上面的示例代码放在这里: http://bitbucket.org/linjunhalida/pyqt-i10n-example

Minecraft介绍

| Comments

什么是minecraft?

随机生成的世界, 完全自由建设, 合成系统, 晚上的怪物, 铁路

下雪了

image

未来世界

image

6英里

视频

图片

多说无益, 直接点开来玩吧

97块人民币, 在线帐号, 至少3个月不腻, 值了!

爽点在哪里?

  • 一个随机生成的世界
  • 你可以很简单地建造
  • 资源需要自己去开采, 为了宝石, 需要挖到地底
  • 合成建造一些奇奇怪怪的东西, 比如铁路, 玻璃, 逻辑电路, 过山车就不算什么了, 有人做了CPU出来..
  • 多人模式, 可以合作建造, 可以玩RPG, 可以战争..
  • 可以在浏览器内打开(java写的)

如何开始?

可以看 wiki , 里面有详细的帮助.

minecraft定制

官方论坛有专门的区域讨论这个.

同步minecraft文件

为了好看, 我加了几个显示模组:

minecraft修改

修改器目录

但我在ubuntu下面, 只有MCPlayerEdit最好用, 因为是python的.

搭建minecraft服务器

如何搭建官方服务器

第三方工具 McMyAdmin

ubuntu下面注意!

因为minecraft是用java写的, 会和ibus输入法冲突(找了半天才知道), 造成无法输入键盘命令, 玩之前需要:

pkill ibus

资源

我玩的游戏

| Comments

虽然有点无聊, 但是还是整理一下那些能让我通宵, 或者至少沉迷一段时间的游戏, 按照时间排列, 太早以前的就不去管它了.

adom

很早的时候迷roguelike, 但是无论是nethack/crawl都玩不进去, 可能是一层层的地牢让我心生恐惧吧. 最后我还是在有城镇的ADOM里面坚持了下去. 不过当步入火焰层烧掉了我大半载重之后, 就放弃了.

cortex command

Cortex Command介绍

这款游戏让我通宵了. 完成度不高, 但是能够建设基地, 爽快的射击与杀戮, 以及物理系统带来的纷飞碎块, 真的让我沉迷了好一阵子. 现在还待在我的硬盘里面. 游戏性能和CPU成正比.

drawf fortress

Drawf fortress介绍

又是一款字符界面游戏, 又是建设基地, 多层, 自由活动的矮人, 随机生成的世界, 操作非常复杂, 以前接触过, 但是在操作面前退步了. 终于有机会玩会了, 但是因为要想很多东西, 我智能不够, 玩到一定程度就停止了.

minecraft

minecraft介绍

随机生成的世界, 完全自由建设, 合成系统, 晚上的怪物, 铁路, 作者赚了几百万欧元.

这款游戏让我通宵了.

reStructuredText介绍

| Comments

什么是reStructuredText?

一种写文档的方式. 简称: ReST

  • 简单, 现场学,现场会
  • 易读
  • 方便生成html/pdf等其他格式

怎么玩?

不多说, 直接用: http://goo.gl/1jNF4

语法

There should be one— and preferably only one —obvious way to do it.

google: rest

http://docutils.sourceforge.net/docs/user/rst/quickstart.html http://docutils.sourceforge.net/docs/user/rst/quickref.html

如何生成其他格式

需要安装docutils

  • html: 有个东西叫rst2html:

    rst2html xxx.rst xxx.html
    
  • pdf: 有个东西叫rst2pdf:

    rst2pdf xxx.rst
    
  • latex: 有个东西叫rst2latex:

    rst2latex --input-encoding=utf-8 --output-encoding=utf-8 xxx.rst >> s.tex
    

python code

1
2
3
4
5
from docutils.core import publish_string
content = publish_string(
    source="doc here"
    writer_name='html'
    )

我用它来干什么?

  • 写博客
  • 写文档
  • 问题: 好像没有支持ReST的网站..

连接

  • 官方网站: ReST

Pyqt介绍

| Comments

最强大的GUI库 — PyQt4

Authors ~ 机械唯物主义

<[linjunhalida@gmai.com](mailto:linjunhalida@gmai.com)\>

一个简单的实例

  • 计算器
  • 10分钟

image

代码

image

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
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class Caculator(QDialog):
    def __init__(self):
        super(Caculator, self).__init__()
        #widgets
        self.leInput = QLineEdit()
        self.lwResult = QListWidget()
        #layouts
        l = QVBoxLayout(self)
        for w in self.leInput, self.lwResult:
            l.addWidget(w)
        #events
        self.leInput.returnPressed.connect(self.caculate)

    def caculate(self):
        data = unicode(self.leInput.text())
        if not data: return
        self.leInput.clear()

        try:
            result = unicode(eval(data))
        except Exception as e:
            result = unicode(e)

        self.lwResult.addItem(result)


def main():
    app = QApplication([])
    Caculator().exec_()

if __name__=="__main__":
    main()

类层级

QObject
   |----- QWidget
             |----- QDialog
             |----- QLineEdit
             |----- QListWidget

layout

image

layout

  • 层级:

    QDialog (QVBoxLayout)
       |----- QLineEdit
       |----- QListWidget
    
  • 代码:

1
2
3
l = QVBoxLayout(self)
for w in self.leInput, self.lwResult:
    l.addWidget(w)

Signal and Slot in Qt

image

Qt和PyQt 事件机制区别

  • Qt:
1
this->connect(leInput, SINGAL(returnPressed()), this, caculate))
  • PyQt:
1
self.leInput.returnPressed.connect(self.caculate)

一个复杂的实例: 扫雷

  • 花费时间: 2个晚上, 基础:2.5小时, 一点点提升:1小时
  • 扫雷下载: pyqtmine

image

UI designer

image

UI with Code

1
2
3
4
5
form, base = uic.loadUiType("score.ui")
class ScoreDlg(QDialog, form):
    def __init__(self):
        super(ScoreDlg, self).__init__()
        self.setupUi(self)

Event

1
2
3
4
5
6
7
8
def mouseReleaseEvent(self, event):
    if event.button() == Qt.LeftButton:
        ...

def paintEvent(self, event=None):
    p = QPainter(self)
    ...
p.drawLine(mx+i*sx, my, mx+i*sx, my+y*sy)

其他强大特性

  • 足够多和好用的控件/自定控件/整合到designer中
  • webkit/script支持
  • 强大/方便/快速的绘图控件
  • 富文本/文本解析
  • 多国语言支持
  • 其他第三方控件支持: pyqwt

发布

pyinstaller!

资源

  • PyQt安装 ~ – ubuntu:

            sudo apt-get install pyqt4-dev-tools
    
    -   windows可以下载一个python包:
        [pythonxy](http://www.pythonxy.com)
    
  • 学习材料 ~ – qt 以及 pyqt 官方网站

    -   书籍请google: pyqt book or qt book
    
    -   中文资料: [qteverywhere](http://www.qteverywhere.com/)
    

所谓的你情我愿

| Comments

image

今天看到帖子: http://www.douban.com/note/97807441/ , 带来不少争议, 一句两句说不清楚, 特此专门发文阐述.

全文转载:

今天跟某留学海外的经济学高材博士生简短对话,是从去沃尔玛买东西是不是不道德开始的(其实我也是去沃尔玛的,所以完全没有任何道德优越感)。

我说起有个纪录片是控诉沃尔玛的。她骤然很激动,说最受不了的就是这种了,这是你情我愿的事情,你既然接受了这工作,就没什么好抱怨的。

我对经济学一窍不通,很傻很天真的问:那不能老板拿少点,给员工多一点吗?

她说:你凭什么要让老板少拿呢?

我说:那你凭什么不让工人多拿呢?为什么老板不需要限制自己的欲望,而工人要限制自己的欲望呢?

她说:这是你情我愿的事,你可以到别的地方去工作啊。

转载完了. 你支持哪一方?

作为一名普通人, 很少有机会能够以企业家的视角来思考问题, 往往是把自己带入到员工这个角色中, 感受员工的情绪:

  • 每天辛苦工作
  • 拿到的工资却很少
  • 会有被炒掉的危险

但是, 作为一个明事理的人, 可以利用情绪来感受环境, 但是不能被情绪所左右, 不能成为情绪的奴隶, 在思考问题的时候, 要静下心来, 想清楚, 弄明白.

先看清楚问题: 员工工作辛苦, 企业家是不是应该给员工更多的好处? 是不是应该给员工更多的保障?

我们眼中的很多企业家, 往往一毛不拔, 压榨员工, 给我们一个很不好的印象, 并且, 我们从小就得到教育: 企业家是靠榨取剩余价值来获得利润的. 但是我们有没有想过, 事实是不是这样?

回到真实世界. 如果你有观察过做小生意的人, 一开始都是自己辛苦工作, 然后摊子做大, 人手不够, 再去雇人. 因为成本因素, 会去让员工努力工作. 如果你做过生意, 应当知道: 雇人不好雇: 工资少了人不来, 不去监管人偷懒.

我们都认为企业家剥削员工, 那么有没有见过:员工剥削企业家? 作为员工的自己, 是不是找到机会就会偷懒? 是不是能多拿点工资就多拿? 从不会期望减少工资? 想想.

现在回到沃尔玛. 假如世界上没有沃尔玛, 那么原先那些沃尔玛的员工, 是不是更不好找工作? 是不是有人强迫他们去沃尔玛工作, 有了沃尔玛, 他们是不是多了更多的工作机会, 多了更多的选择?

再进一步. 在沃尔玛雇用员工之前, 对员工有没有义务? 雇用之后是不是有义务了? 这个义务是否是交换员工的服务? 在雇用员工的合约签订的时候, 员工是否有自主权? 如果待遇少了, 员工是不是能不签合约? 签了合约, 员工是不是应该服务以换取企业给的薪资, 是不是说, 既然签订了合约, 就是员工和企业家达成了:公平交易?

那么回到最开始的问题: 员工工作辛苦, 企业家是不是应该给员工更多的好处? 是不是应该给员工更多的保障?

如果说当初员工签约的时候已经是公平交易了, 那么为什么企业家应该付出更多? 这样是不是不公平? 为什么我们会希望这样的事情? 是不是因为情绪的影响? 还是什么其他更重要的原因?

这是我们每个人都应该想, 并且应该想清楚的问题, 这关乎我们的人生观和世界观, 虽然不会有直接的影响, 但是会潜移默化到我们自己将来会走的路, 甚至影响到其他人走的路.

如果你想要弄清楚这些问题, 应该看看张五常的 经济解释 , 以及曼昆的: 经济学原理

Pyqt编写的程序如何发布

| Comments

2009年12月3号研究了一下如何发布pyqt的程序,整理内容如下:

pyqt是qt图形库对于python编程语言的一个绑定,qt是著名的跨平台图形开发库,专业,易用,以及企业级别支持,文档齐全。python是一个简单易用的解释语言。不过这篇文章是关于如何发布pyqt程序的,那么读者应该都知道这些,我就不多介绍了。

我们用pyqt开发完程序的时候,得到的是一堆python源代码,以及一些资源文件,比如用到的图片,声音什么的。程序在我们开发平台上可以运行,但是我们还需要想办法让客户机也能够用我们的代码。

我们需要做2件事情:一个是把源代码打包成可以放到任何电脑都能够执行的程序,另一个是做一个安装程序,好方便安装到客户机上。

我现在选择py2exe作为打包的工具,nsis作为生成安装程序的工具。

py2exe

nsis

nsis下载后文档中有详细的介绍,安装目录中含有许多的示例。

我写的示例在 这里

稍微解释一下: 比如,我写了一个新的专案,名称叫test_pyqt,新建了一个这样的文件夹。 里面有一个main.py源代码。同时还有一个res的资源目录。 为了能够利用py2exe打包,需要新建一个setup.py的设置文件。

几个难点整理如下: 根据py2exe里面说的,pyqt需要包含sip(我也不知道这是什么东西,估计是C++转python的时候要用到的。。),下面的脚本含有具体的设置。 编译好的文件还需要一些额外的dll文件(主要是针对没有加sp的XP版本运行时出现“程序出错”报错的状况),放在dll文件夹里面,打包的时候要加上(dll文件在上面的示例中)。我没有研究出如何把这些文件加到可执行文件里面的办法,如果你知道的话,就告诉我。

内容如下:

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
#!/usr/bin/env python
#-*- coding:utf-8 -*-
# ---------------------------------
# 打包程序
from distutils.core import setup
import py2exe,glob

setup(windows=[{
                "script": 'main.py',
                #应用程序图标
                "icon_resources":[(1, "res/py.ico")] }],
      data_files=[
                  #资源文件
                  ("res", glob.glob("res/*.*")),
                  #因为客户机可能缺少部分开发文件造成无法运行程序,需要打包一些文件
                  (".",glob.glob("dlls/*.*")),
                  ],
      options={"py2exe":{"includes":["sip"],
                         "optimize":2,
                         #打包成一个文件,加快读取速度
                         "compressed":1,
                         "bundle_files":2,
                         #文件放在哪里
                         "dist_dir":"temp/dist",
                         #少了个文件,不管它
                         "dll_excludes":["MSVCP90.dll"],
                         },
               },
      zipfile=None,)#一个文件

#删除build临时目录
import shutil
shutil.rmtree('build')

执行:

python setup.py py2exe

以上语句需要把python的目录加到path里面去,或者你可以在python前加上完整的python安装目录. 我是加path的,因为这样使用python更方便。

之后,会生成temp/dist文件夹,里面就是一个main.exe可执行文件了,还有res文件夹。

之后是生成安装文件,新建一个installer.nsi文件,内容如下(因为比较长,放到最后)。

内容比较多。当时我在做的时候,看了很多的文档才知道具体怎么做。为了方便,你还是用我的示例吧。

下面的内容含有多语言,license页面,安装内容页面,安装目录页面,以及反安装页面。

如果你感兴趣的话可以自己研究,我是被nsis细节给累倒了。

这个文件你只需要改下面软件名称的部分,它会自动把dist打包安装到program files里面,生成执行文件链接到桌面以及菜单项中。

对了,主执行文件的入口是main.py这个源代码。

文件写好后,鼠标右键菜单中有一个compile nsis script的选项,点击就可以生成安装文件。

具体的细节可以看我上面示例的压缩文档。我写了一个makefile来方便快速执行操作(别告诉我你不会用make)。 该示例在windows xp,python2.6,nsis2.46,pyqt4.5,py2exe上测试通过。等以后考虑跨平台版本:

#coding:utf-8

;软件名称
!define NAME "test_pyqt"

;主执行文件
!define EXE "dist\main.exe"

;样式
XPstyle on

;输出的安装文件
OutFile "temp/${NAME}_installer.exe"

;默认目录
InstallDir $PROGRAMFILES\${NAME}

; 检查是否已经安装过
InstallDirRegKey HKLM "Software\${NAME}" "Install_Dir"

;需要管理员权限
RequestExecutionLevel admin

;--------------------------------

; 页面

Page license
Page components
Page directory
Page instfiles

UninstPage uninstConfirm
UninstPage instfiles

;--------------------------------

; 安装主目录
Section "main"

SectionIn RO

; Set output path to the installation directory.
SetOutPath $INSTDIR

; 需要安装的程序
File /r "temp\dist"

; Write the installation path into the registry
WriteRegStr HKLM SOFTWARE\${NAME} "Install_Dir" "$INSTDIR"

; Write the uninstall keys for Windows
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${NAME}" "DisplayName" "${NAME}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${NAME}" "UninstallString" '"$INSTDIR\uninstall.exe"'
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${NAME}" "NoModify" 1
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${NAME}" "NoRepair" 1
WriteUninstaller "uninstall.exe"

SectionEnd

; 开始菜单
Section "开始菜单"

CreateDirectory "$SMPROGRAMS\${NAME}"
CreateShortCut "$SMPROGRAMS\${NAME}\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0
SetOutPath $INSTDIR\dist
CreateShortCut "$SMPROGRAMS\${NAME}\${NAME}.lnk" "$INSTDIR\${EXE}" "" "$INSTDIR\${EXE}" 0

SectionEnd

; 桌面快捷方式
Section "桌面快捷方式"
SetOutPath $INSTDIR\dist
CreateShortCut "$DESKTOP\${NAME}.lnk" "$INSTDIR\${EXE}" "" "$INSTDIR\${EXE}" 0
SectionEnd

;--------------------------------

; Uninstaller

Section "Uninstall"

; Remove registry keys
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\"
DeleteRegKey HKLM SOFTWARE\${NAME}

; Remove directories used
Delete "$DESKTOP\${NAME}.lnk"
RMDir /r "$SMPROGRAMS\${NAME}"
RMDir /r "$INSTDIR"

SectionEnd

;--------------------------------
; 语言部分
; First is default
LoadLanguageFile "${NSISDIR}\Contrib\Language files\English.nlf"
LoadLanguageFile "${NSISDIR}\Contrib\Language files\SimpChinese.nlf"

; License data
; Not exactly translated, but it shows what's needed
LicenseLangString myLicenseData ${LANG_ENGLISH} "license.txt"
LicenseLangString myLicenseData ${LANG_SIMPCHINESE} "license.txt"
LicenseData $(myLicenseData)

; Set name using the normal interface (Name command)
; LangString Name ${LANG_ENGLISH} "English"
; LangString Name ${LANG_SIMPCHINESE} "Simplified Chinese"
; Name $(Name)

;--------------------------------
Function .onInit

;Language selection dialog

Push ""
Push ${LANG_ENGLISH}
Push English
Push ${LANG_SIMPCHINESE}
Push "Simplified Chinese"
Push A ; A means auto count languages
; for the auto count to work the first empty push (Push "") must remain
LangDLL::LangDialog "Installer Language" "Please select the language of the installer"

Pop $LANGUAGE
StrCmp $LANGUAGE "cancel" 0 +2
Abort
FunctionEnd
[/sourcecode]

2010/10/29修改: 其实现在pyinstaller用起来更方便, 直接build就可以了. python2.6以后的版本需要下载开发版本使用.

用python画地形图

| Comments

看到一篇 好文,关于如何生成一个随机地形图的, 方法是用分形。于是手痒,花了一个下午和半个上午的时间把用python把这个事给干了。 下面是生成的2维和3维效果,代码在 这里

image image

回的四种写法

| Comments

2010/5/30聚会,沈大侠分享了一下python dict get的四种方法:

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
# method 1
# 采用异常捕捉来处理KeyError
# 查询1次
try:
    v = data[k]
except KeyError:
    v = 12

# method 2
# 取值前先进行条件判断
# 查询2次
if data.has_key(k):
    v = data[k]
else:
    v = 12

# method 3
# 和method2类似,只是利用in取代函数调用
# 查询2次
if k in data:
    v = data[k]
else:
    v = 12

# method 4
# 函数调用
# 查询1次
v = data.get(k)
if v == None:
    v = 12

提到几点: 函数调用是比较慢的,不如data[key]和key in data快。 所以method2完全可以被method3替代。 method4在多数情况下也没有method2好。

异常处理因为需要建立Error的对象,是最慢的。 所以method1不很适用命中率低的状况。

method1和method4都只查询一次, method2和method3都要查询两次, 在某些查询是性能瓶颈的时候,不如method1和2快。

为了对上面的估计作实际验证,我写了测试程序,如下:

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
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import time, json

def test(data, k, count):
    times = []

    start = time.time()
    for i in range(count):
        #method 1
        try:
            v = data[k]
        except KeyError:
            v = 12
    end = time.time()
    print "method 1 spend time: %f s." % (end - start)
    times.append(end - start)

    start = time.time()
    for i in range(count):
        #method 2
        if data.has_key(k):
            v = data[k]
        else:
            v = 12
    end = time.time()
    print "method 2 spend time: %f s." % (end - start)
    times.append(end - start)

    start = time.time()
    for i in range(count):
        #method 3
        if k in data:
            v = data[k]
        else:
            v = 12
    end = time.time()
    print "method 3 spend time: %f s." % (end - start)
    times.append(end - start)

    start = time.time()
    for i in range(count):
        #method 4
        v = data.get(k)
        if v == None:
            v = 12
    end = time.time()
    print "method 4 spend time: %f s." % (end - start)
    times.append(end - start)

    return times

def main():
    print "test hit"
    data = {'a': 12}
    k = 'a'
    times1 = test(data, k, 1000000)
    print

    print "test not hit"
    data = {'a': 12}
    k = 'ab'
    times2 = test(data, k, 1000000)
    print

    print "test data IO"
    data = {'a': 12}
    k = 'a'
    fd = FileDict(data)
    times3 = test(fd, k, 5000)
    print

    import numpy as np
    import matplotlib.pyplot as plt

    ind = np.arange(4)
    p1 = plt.bar(ind, times1, width=0.2, color='r')
    p2 = plt.bar(ind+0.2, times2, width=0.2, color='g')
    p3 = plt.bar(ind+0.4, times3, width=0.2, color='b')
    plt.xticks(ind, ('method 1', 'method 2', 'method 3', 'method 4') )
    plt.legend( (p1[0], p2[0], p3[0]), ('hit', 'not hit', 'IO') )
    plt.show()

class FileDict:
    def __init__(self, data):
        open('temp.txt','w').write(json.dumps(data))

    def get(self, key):
        return json.load(open('temp.txt'))[key]
    __getitem__ = get

    def has_key(self, key):
        return json.load(open('temp.txt')).has_key(key)
    __contains__ = has_key

if __name__=="__main__":
    main()

结果如图 (ubuntu9.10 + python2.6):

image method3性能比method2好,method1在not hit的情况下时间消耗最多, 在get消耗大的情况下method1和method4消耗的时间要比method2和method3少一半。