Tuesday, December 23, 2008

在Thunderbird里导入foxmail的邮件

之前不小心误删过一个学期的email。邮件服务器是imap的,俺没选本地保存,几个thunderbird客户端就都丢了这些email。后来发现我foxmail底下保存了那些email。就决定导回thunderbird里。步骤如下:
1 在foxmail里选中这些邮件,选择导出。默认的将每一封email存成eml格式的文件
2 网上很多做法是借助outlook 来中转。我完全不会摆弄outlook,放弃。但是选择安装了import/export tools这个thunderbird插件。在thunderbird的“本地文件夹”里新建一个文件夹,借助那个插件导入eml文件。用这个新文件夹中转是因为这个插件说不能直接在imap的帐户底下导入。
3 把新文件夹里的email拖到imap的帐户的inbox里。它就会自己和服务器同步去了。然后就可以把那个新文件夹删了。

好久不用foxmail,今天用了一下6.5beta,感觉进步不少。界面比thunderbird要出色了。也许哪天就又换回foxmail了吧 呵呵

Sunday, December 21, 2008

[Linux]Ubuntu自带pdf阅读器无法显示某些pdf文档的中文问题

Ubuntu自带的Evince非常小巧和轻量。可是有时候有些中文文档无法正确显示中文。可以通过如下方法尝试解决。首先安装xpdf的中文支持:
$sudo apt-get install xpdf-chinese-simplified
$sudo apt-get install xpdf-chinese-traditional

如果还不行,安装poppler相关软件,好像是用于pdf渲染用的。
$sudo apt-get install poppler-utils
$sudo apt-get install poppler-data

Tuesday, December 09, 2008

Ubuntu以及MacOS下使用街机模拟器Mame

Mame是一款经典的街机模拟器。但是由于它是Windows下native的,自然有在Linux和MacOS上的移植。这两天捣鼓了一下这个东西,开始玩合金弹头。
Ubuntu:
1 安装sdlmame (linux上的mame版本): sudo apt-get install sdlmame
2 生成配置文件:sdlmame -creatconfig
3 到/etc/sdlmame下修改mame.ini。 rompath那行把添加进去自己存放rom的路径。比如我用的就是/home/apc999/.mame/roms。另外如果你是ATI显卡的话, 最好把video那行的opengl改成soft。因为ubuntu下ATI显卡驱动有问题。
4 把你的rom文件放在你指定的rompath底下,如果下回来就是zip格式的话不用去解压直接放。
这个时候理论上你可能还是玩不起来游戏,因为很多游戏需要相关的bios文件。我是去国治精品屋下载了“Mame Plus!国治2009版”模拟器。不过这个是运行于windows上的。它包括了很全的bios文件。我们只需要把它roms目录底下的那些zip文件(他们都是bios文件)都考过来,放在你的rompath底下就可以了。
MacOS:
安装的是MacMame。然后把那些bios文件考在目录~/Documents/MacMAME User Data/ROMs底下就可以了。

Sunday, December 07, 2008

[Python]Python 3.0来了

经历了3年的开发,Python 3.0 (Py3k)在千呼万唤声中 ,终于在2008年12月3号正式发布了。用Guido同学(Python语言的缔造者)自己的话说,Python这些年经历了迅猛发展,已经开始有点违背了Python的"There's Only One Way To Do It"的哲学理念。Guido同学认为Python之所以有今天正是得益与这一与Perl "There is more than one way to do it"相反的理念。所以他需要做一些“清理门户”的事情。因此,我们就有了Python 3.0这一"里程碑"--Python 3.0不提供向下兼容性。换言之,你的2.x的库或者代码,可能会无法运行在Python 3.x当中。

Python 3.0当中有哪些变化呢?http://docs.python.org/3.0/whatsnew/3.0.html给出了官方的解释。首先映入眼帘的便是,print的语法被改变了。如今print降格为了普通一介函数,需要用print(file=xxx, str1, str2,...)来调用了。其实我很怀念原先print>>xxx, str1, str2 ...的语法,简洁而一目了然。

另外我觉得比较大的改变还有
  • dict.keys() dict.values()以及dict.items()不再返回list类型的值。所以如果想要k=d.keys();k.sort() 就得写成 k=sorted(d)
  • range现在像以前的xrange那样来工作(之前range直接返回一个list而xrange是返回一个可以yield同样结果的迭代器,以提高效率)。xrange下岗了。
  • 1/2现在的结果是float了,如果要得到截尾的效果,需要用1//2。这个好,再也不用痛苦的写上a*1.0/b/c了
  • <>下岗了。现在只能用!=了。这点不理解。
  • list.sort()现在可以多一个key 参数。比如list.sort(key=myhash),则myhash为一个1参数1返回的函数,list就依据这个myhash来对其包含的元素排序。乌拉!这点好,不用再去重载cmp函数了。早就盼着这一天了
  • 支持如同ML当中的pattern matching: (a, *rest, b) = range(5)
    可以得到 a=0, rest=[1,2,3], b=4
  • 终于到了我最关心的一点:Python 3.0里提供了函数参数以及返回值的注解功能。比如你可以 定义函数 def foo(para1: "the 1st input", para2: "the 2nd input") -> "final result" 这里使用了字符串作为参数和返回值的注解。或者你可以 def bar(para1: int, para2: list) -> float 这样来用类型定义。不过需要特别指出的是,python解释器本身不对注解做出任何反应。这里注解的作用是提供给第三方来infer参数意义或者做typechecking的。
说道这里,就稍微走题一下吧。Python是一种Dynamic Typing的语言。变量的类型是在运行期才infer出来,而不像C/C++/Java等Static Typing在编译期就已经决定了。Dynamic Typing的优点在于方便灵活,但如果程序规模一大,纠错就是一个很头疼的事情。Static Typing 很多错误可以在编译期就发现。我自己的一个感觉就是用Java写程序如果“编译”通过了,运行期出错的概率比Python小的多。所以一直都很希望Python能有可选的Static Typing 的功能。事实上,Boo 就是一种Static Typing的Python-like语言,而Cobra 则是提供了可选Static Typing的Python-like语言。关于Python是否需要这一功能,可以看一下Guido同学的帖子"Adding Optional Static Typing to Python"。总体而言可以说Guido同学是反对这一想法的。因为他觉得这会把Python简洁的语法弄的凌乱而丑陋并且对Python解释器的执行速度也是一大考验。回到Python 3.0的注解机制上来,这算是一种折中吧--如果你需要typecheking, OK,我们提供场地,你请用第三方来完成吧,但是后果你自负。好吧,虽然这不是我想要的,但是总比没有强吧。

Python 3.0究竟会表现如何?时间会告诉我们,让我们拭目以待。

Sunday, November 30, 2008

[Python]实现Console下路径输入的补全

因为要用脚本处理一些log,每次运行都要输入待处理的log的路径。可是我存放的log路径太复杂 log自己名字也很复杂,输入起来很麻烦。就想在python里借用shell的路径补全功能。Python里有readline这个module可以提供补全的基本功能,当然需要你自己给它一个completer(text, state)函数从而使它知道如何去补全。另外还有一个cmd module提供简单的命令行界面。用这两者就可以实现我们需要的功能。
import cmd
import string, sys
import os
import readline
class CLI(cmd.Cmd):
def __init__(self):
cmd.Cmd.__init__(self, "tab")
self.prompt = 'input the path:'
self.path = None
readline.set_completer_delims('/\\')
def onecmd(self, path):
if os.path.exists(path):
self.path = path
return path
else:
print "%s not exists"%(path)
return None
def complete(self, text, state):
if state == 0:
origline = readline.get_line_buffer()
line = origline.lstrip()
stripped = len(origline) - len(line)
begidx = readline.get_begidx() - stripped
endidx = readline.get_endidx() - stripped
self.completion_matches = self.completepaths(text, line, begidx, endidx)
try:
return self.completion_matches[state]
except IndexError:
return None
def completepaths(self, text, line, *ignored):
(head, tail) = os.path.split(line)
matches = []
if head == "":
p = "."
else:
p = head
if os.path.exists(p):
filelist = os.listdir(p)
matches = [f if os.path.isfile(os.path.join(head, f))\
else f+os.sep for f in filelist if f.startswith(tail)]
return matches
def get_path(self):
self.cmdloop()
return self.path
def get_path():
cli = CLI()
return cli.get_path()

这里我们继承了Cmd类。但是重载了complete这个函数。这个函数是在用户按下tab键呼叫补全的时候被调用。
使用这个小程序只要import这个文件以后直接调用get_path就可以了.
补充:后来发现了一个小bug已经做了修改。cmd module里面在cmdloop()这个函数里就设定了completer_delims (分隔符)。问题在于默认的分隔符里面有很多合法的linux文件名字符比如 “-”这样会导致tab补全的时候出一些问题。 所以我们需要在这之前设置好。这里我们就在__init__初始化的时候设置成/以及\。

Tuesday, November 25, 2008

[Linux]几个常用的网络相关的工具

  • ttcp
    测量两台主机之间的tcp/udp throughput
    实例:
    第一步1: 在receiver 主机上打开ttcp, 进入接收模式
    [receiver:~]$ttcp -r -v -s
    ttcp-r: buflen=8192, nbuf=2048, align=16384/0, port=5001  tcp
    ttcp-r: socket
    第二步2: 在sender端向receiver发送文件测试传输速度
    [sender:~]$ttcp -t receiver < testfile
    ttcp-t: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp -> receiver
    ttcp-t: socket
    ttcp-t: connect
    ttcp-t: 20197 bytes in 0.03 real seconds = 740.32 KB/sec +++
    ttcp-t: 3 I/O calls, msec/call = 9.09, calls/sec = 112.60
    ttcp-t: 0.0user 0.0sys 0:00real 0% 0i+0d 0maxrss 0+2pf 4+1csw
  • iperf
    iperf也是测量网络throughput的常用工具之一. 用法和ttcp类似.
  • iptables
    iptables是Linux下的软件firewall
    https://help.ubuntu.com/community/IptablesHowTo
    查看当前iptables的设置
    $sudo iptables -L
  • ipfw
    ipfw其实是FreeBSD底下的软件firewall。可以非常方便的用来traffic shaping.
    实例:
    • 如下命令添加一个virtual pipe用于所有inbound的ip traffic。并且设定这个pipe bandwidth为50Kbit/s buffer size为50
      $sudo ipfw add pipe 1 ip from any to any in
      $sudo ipfw pipe 1 config bw 50Kbit/s queue 50
      
    • 如下的命令模拟ADSL:
      sudo ipfw add pipe 3 ip from any to any out
      sudo ipfw add pipe 4 ip from any to any in
      sudo ipfw pipe 3 config bw 128Kbit/s queue 10 delay 1000ms
      sudo ipfw pipe 4 config bw 640Kbit/s queue 30 delay 1000ms
      
    • ipfw除了使用pipe来模拟link,还可以使用queue来模拟队列。等我知道怎么用了再来写。
  • systat
    Freebsd下监视系统的命令,可以显示CPU、I/O、内存、虚拟内存、mbufs、磁盘IO、网络状态等信息等。
    用法:
    systat [-display] [refresh-interval]
    • display 为我们所要显示的信息项目,我们也可以在进入 systat 后通过输入“:display”变更显示项目。可选项:
      pigs 显示目前系统中使用 CPU 最多的行程名称。如果所有行程的 CPU 使用量未满 100%,则多出来的部份显示为 IDLE。icmp 统计目前 ICMP 封包的进出情形。icmp6 显示 IPv6 的 ICMP 封包进出情形。ip 显示 IP 层的封包统计及 UDP 封包信息。ip6 和 IP 一样,但只显示 IPv6 的封包。tcp 显示 TCP 的封包统计。iostat 显示 I/O 状况统计,并分类为各种模式显示。swap 显示目前各个储存空间上的虚拟内存的使用情形。mbufs 显示 mbufs 被使用的状态。vmstat 这是我们最常用的显示模式,它显示了最多的信息,包含 I/O、虚拟内存、mbufs、网络等信息。netstat 显示网络的使用情形。ifstat 显示各个网络适配卡的使用情形。
    • refresh-interval 参数是需要多长时间采样一次系统数据输出到屏幕,单位是秒。
    实例:
    systat -v 1
    我们打开v选项(vmstat的缩写),每隔1s更新一次。
  • netstat 可以用来查看当前网络所有链接, 也可以用来查看路由信息,比如
    $ netstat -nr
    Routing tables
    
    Internet:
    Destination        Gateway            Flags        Refs      Use   Netif Expire
    default            10.1.10.1          UGSc           23       36     en0
    10.1.10/24         link#4             UCS             6        0     en0
    10.1.10.1          0:22:2d:7b:12:fa   UHLWIir        24       22     en0    134
    10.1.10.10         80:ea:96:e4:f6:93  UHLWI           0        7     en0   1190
    10.1.10.11         d8:d1:cb:91:6d:aa  UHLWI           0        0     en0    691
    10.1.10.15         8c:2d:aa:5a:a7:1f  UHLWI           0       58     en0    733

Monday, November 24, 2008

emacs与vi常用指令对照

这个学期的Type Systems需要学习用Twelf这个语言。简单的说是CMU搞出来的一种(目前主要用于教学的)Logic Programming的语言。因为它提供了emacs的mode,会比调server出来运行要方便快捷。再加上Carl一个劲的鼓吹Computer Scientists是使用emacs的而不是vi。我正好用这个机会push自己多练练emacs。在这个帖子里集中记录我常用到的指令以及和vi的对照。毕竟vi短小精悍而且和less之类的指令相通不可能完全不用。
操作 emacs vi
文件操作:
打开文件C-x,C-f,<filename>:sf <filename>
保存C-x,C-s :w
退出C-x,C-c:q
编辑
选择C-space (设立标记)v (进入visual模式)
拷贝M-wy
剪切C-wd
粘贴C-yP
撤销上一个指令C-x,uu
删除一行C-kdd
拷贝一行
yy
移动
跳至第n行M-g,g,<n>:<n>
搜索
找到patternC-S,<pattern><patern>
其他
执行n个指令C-u,<n>,<cmd><n> <cmd>

Thursday, November 20, 2008

[Python]使用ansi color code 让console五颜六色

写了一个Python小程序, 用于输出带ansi color code的字符串,使得在支持vt100的终端上能看见五颜六色的输出。

ESC = chr(27)
# 字体
a_default = 0
a_bold = 1
a_italic = 3
a_underline= 4
# 前景颜色
fg_black = 30
fg_red = 31
fg_green = 32
fg_yellow = 33
fg_blue = 34
fg_magenta = 35
fg_cyan = 36
fg_white = 37
# 后景颜色
bg_black = 40
bg_red = 41
bg_green = 42
bg_yellow = 43
bg_blue = 44
bg_magenta = 45
bg_cyan = 46
bg_white = 47

def color_code(a):
return ESC+"[%dm"%a

def color_str(s, *args):
cs = ""
for a in args:
cs += color_code(a)
cs += s
cs += color_code(a_default)
return cs

用法
比如你可以用

print color_str("hello world", fg_red, bg_black, a_bold)

来生成黑底红字的加粗的hello world

Wednesday, November 19, 2008

Screen 小结

screen在mitbbs的linux版上被称为震版之宝。minhong推荐下我用了一下,果然非常好用。
这里先占坑。

基本用法:
  1. 在term下键入screen。会出现一些提示,然后就是先前的shell。这时候与普通shell的唯一区别在于你可以使用ctrl+a d (先按ctrl + a, 然后按d)退出这个screen session。这个session以及在这个session中运行的程序将在没有你的监督下继续运行,哪怕你是远程登录到这台主机上而远程登录又中断了。
  2. 查看当前主机上运行了多少个session, 以及每个session叫什么名字:
    screen -ls
  3. 继续一个离开了的session.如果当前只有一个session,那么直接输入
    screen -r
    如果有多个session, 而你要重入其中的一个:
    screen -r sessionname
  4. 进入一个session后, 键入ctrl+a k 终止当前session. 不像ctrl+a d只是离开这个session, 使用了ctrl+a k之后你就无法再次重入这个session了
  5. screen -S your_fav_name -d your_cmd:新建一个名为your_fav_name的screen会话并执行你的命令.为一个会话起一个名字的好处包括用这个名字来kill掉这个会话,而不用每次都先screen -ls看你这个会话的id.
注意事项:
  1. 在远程主机上执行screen: 如果你是ssh到远程主机上并直接用screen 执行一个命令,比如:ssh user@host screen cmd,有可能得到Must be connected to a terminal.这个错误。 解决方法:使用 ssh的-t选项
  2. 杀死远端的screen进程:当你远程主机使用screen在执行一个命令的时候,你可以登录到这个主机并resume你的screen会话并用ctrl+a k杀死该会话。但是这样要求手动控制而无法使用脚本。一个解决办法是用: "screen -S sessionid -X quit" 向远端主机发送screen窗口命令cmd 。 比如quit的话就是结束这个session。
  3. detach远端的screen 进程。 比如你回家之前在office的机器上用screen执行一个命令且没有detach。当你从家里登录office机器想resume则会被告知,该session没有被detach你无法直接在家resume进去。可以发送用: "screen -S sessionid -X detach"命令过去将其detach,然后再实现重入。
  4. 输入backspace的时候总是出现“Wuff Wuff!“这样的讨厌提示。以及del/backspace工作不正常。可以参见http://ubuntuforums.org/archive/index.php/t-90910.html .我的经验是设置TERM变量。bash 底下可以alias screen='TERM=screen screen',tcsh底下可以alias screen 'env TERM=screen screen'

Thursday, November 13, 2008

[Python]Quine(自产生程式) in Python

Quine是指一个程序,它的输出为自身的源代码。这个学期的OS课里读到Ken Thompson的paper里说到了这样的一个程序。Ken Thompson在83年因为早年对Unix和C语言的贡献而得到了图灵奖。这篇paper 是他的图灵奖演讲文稿。在paper里他提到他在UC Berkeley念书的时候,同学们都热衷于写这样的程序并相互比赛谁的程序短。并且他还提到,如果你们自己没有写过这样的程序,他强烈建议自己来试一试写这个程序,会比由别人告诉你如何得到这个程序要有收获的多。于是我便没有接着往下读这个paper看Ken是如何完成的而是试图用Python来写一个这样的程序。最后得到了这样的程序:
M="print 'M='+repr(M)\nprint M"
print'M='+repr(M)
print M
Python来完成这个任务事实上是相当简洁的。因为repr()这个函数帮助我们完成了很多的工作。

Sunday, November 09, 2008

SSH一点点经验

使用~/.ssh/config
.ssh/config这个文件就是给大家偷懒用的.比如我可以指定:
Host aaa
        User apc999-majia
        Hostname aaa.foo.bar
这样只要输入ssh aaa, ssh就自动帮你链接aaa.foo.bar并且使用用户名apc999-majia.
也可以使用通配符*以及?
Host aaa*
        User apc999-majia
在config文件中还可以指定其他许多有用的选项, 参见:config中的选项


不能使用公钥验证登陆的问题:
Office的机器从某天开始突然不能允许我用public key来ssh 登陆了。排查了很久:
(1)首先看public key和private key是不是对的 -- 对的
(2)检查要登录的机器那端权限设置是不是正确:~/.ssh 应该是0700, ~/.ssh/authorized_keys应该是0600, --对的
于是使用sshd的debug模式来看一看:
sudo /usr/sbin/sshd -d -p 2000: 实现一个2000端口的one shot debug mode,
这样你可以在客户端 ssh -p 2000 HOSTNAME 来尝试一次登陆以提供debug信息。
然后看sshd的log (/var/log/auth.log) 看到 sshd[9564]: Authentication refused: bad ownership or modes for directory /home/xxxxx 。遂去看了一下$HOME的权限, 原来不知道怎么给了组用户w权限。去掉以后就好了。

另外本机~/.ssh/config权限应该是600

登录被要求输入两次密码 (Password, Response)
这是由于使用了SSH version 1会这样, 比如我们用-1选项手动使用version 1登录
$ ssh -1 foo.bar.net
Password:
Response:
而使用version 2(选项-2)则是
$ ssh -2 foo.bar.net
Password:

大多数SSH client 默认先使用Protocol 2.但是FreeBSD的/etc/ssh/ssh_config中默认Protocol 1,2. 所以我们可以修改/etc/ssh/ssh_config(如果你有权限)或者~/.ssh/config(只能管你自己),使得
#Protocol 1,2
Protocol 2,1

想看登录时候的详细信息,比如本地和远端主机如何交互:
ssh -v foo.bar.net
想看更详细的:
ssh -vv foo.bar.net
想看更更详细的:
ssh -vvv foo.bar.net
想看更更更详细的:
请订阅中国电视报

关掉每次登录前Host Key的检查。就是每次登录一个陌生host前被询问:
The authenticity of host 'foo.bar.net (1.2.3.4)' can't be established.
DSA key fingerprint is dc:28:c4:30:85:11:75:8a:61:53:65:1a:a0:50:5e:32.
Are you sure you want to continue connecting (yes/no)?
修改~/.ssh/config
Host *
StrictHostKeyChecking no
这个选项默认的是ask,就是每次都询问

用一台主机做代理登录另目的主机(foo.bar.net):
修改~/.ssh/config
Host foo.bar.net
User bfan
ProxyCommand ssh foo.bar.net -l 用户名 nc %h 22

选项 -o BatchMode=yes
好处是用于脚本批量登录的时候(比如使用我的multissh.py脚本)的时候因为一些系统问题被提问密码,直接当作错误返回。 这样脚本可以当作登录失败重新尝试.

端口转发(Port Forwarding, Tunneling)
比如使用了如下命令:
ssh -L 1234:host2:5678 host1
那么在登录host1期间,我们的本地主机还会打开一个tcp端口1234并监听,所有1234端口接受到的流量通过安全连接转发给host2的5678端口.
命令行参数为 -L local_listen_port:destination_host:destination_port
或者在.ssh/config设置为
LocalForward local_listen_port destination_host:destination_port
参考SSH Port Forwarding

对某台主机不使用Pubkey登录
如果是一次性的
ssh -o PubkeyAuthentication=no  your_hostname
如果是多次性的
PubkeyAuthentication=no写进~/.ssh/config文件对应的条目中

环境变量问题
http://roumenpetrov.info/articles/locale_env_in_ssh_session.html
我在自己机器上设定环境变量LC_CTYPE=zh_CN.UTF-8, 导致在一些远端服务器上出现一些locale的问题.这是因为/etc/ssh/ssh_config文件中设定了
SendEnv LANG LC_*
所以LC_CTYPE环境变量也被送到了远端,导致出现了一些问题. 把LC_*去掉后就好了

Sunday, November 02, 2008

[Python]使用Python中的Lambda演算功能:Y-Combinator的Python实现

最近接触的东西都比较杂。不过感觉好几个方面比较有收获。一是使用PyQt感觉Qt平台的强大和华丽。对我来说它最大的好处是跨平台:我的Mac和Ubuntu都可以很好的支持,程序不用修改就能顺利的运行在不同平台上。二是可以使用Python, 这个好处就不多说了。

由于这个学期选得Type Systems课,接触了一些Lambda演算和ML语言(想歪的同学请自觉面壁)。前半个学期由于赶paper的缘故都没有花时间在上面,况且前面的内容也不是那么有趣(Constructive Logic算是一个小亮点)。现在讲到了Polymorphism(应该是多态吧?)以后,才发觉这里面的博大精深。Lambda演算是一种与被大家熟知的Turing Machine不同的计算模型,事实上它的历史甚至可以追随到Turing Machine之前。Turing本人也对Lambda演算做出过贡献。比起Turing Machine,Lambda演算在形式上要“简单”,思维更接近数学。但是Lambda演算的计算能力被证明是和Turing Machine的计算能力是等价的。Turing Machine上著名的停机问题也有其Lambda 演算版本。而且这个版本其实由Church比Turing更早提出

Lambda演算的基本形式为λx.body。 这里可以把x看成一个函数的输入参数,body看成这个函数的返回值。不过与普通编程语言中的函数不同的是, x可以为一个普通的值变量,也可以为一个函数,还可以是一个类型。简简单单的定义却有无穷的变化。比如Church在Lambda演算的基础上重新定义了正整数。还可以在Lambda演算的基础上把布尔类型以及正整数类型推广化。比如List就是一种generalized的正整数。

Python提供了Lambda算子的功能。下面我就用Python的Lambda算子来实现不动点算子Y-Combinator。有关什么是Y-Combinator可以看一下wiki。简单的说来,给定一个函数g以及不动点算子Y,我们有Y(g) = g(Y(g))。从而我们可以用不动点算子Y来实现g的递归调用。

Y-Combinator in Python:
Y = lambda f: (lambda x: f(lambda n:x(x)(n)))(lambda x: f(lambda n:x(x)(n)))


这样如果你定义了非递归函数,比如阶乘
g =  lambda factorial, k : 1 if k == 1 else factorial(k-1)*k

或者更容易理解的方式是这样:

def g(factorial, k):
if k == 1:
return 1
else:
return factorial(k-1)*k

就可以用 Y(g) (k) 来递归求k的阶乘。

Ref: http://siddhi.blogspot.com/2007/08/y-combinator-in-python.html

Saturday, November 01, 2008

[Python]Python2.6内建函数(未完)

Python用了很久了,但一直没有系统的学习一下它的内建函数, 也就是在__built-in__这个module里的函数。这些函数都是在直接默认在namespace中不需要import 任何其它module来获得的。所以可以想象,也是最常用最有用的那部分函数。决定今天补上这个差事。也是为了使自己能够熟系很多不那么常用的功能,写出更加有效率的代码。

__import__ 最常使用的import函数会调用__import__。python 提供这个内建函数是为了让用户可以改变import的语法,比如提供自己的import 函数

abs(x) 返回绝对值。按说应该放在math module里面, 但是估计太常用了就放在built-in里面了。同样的还有max, min

all(iterable), any(iterable) 前者返回True当所有iterable元素为“True”,后者返回True当有一个元素为“True”。装13的话可以这么说,一个是全称量词一个是存在量词。不过要注意的是, 我这里True打了引号是因为不仅仅是Boolean的True值。事实上,在Python当中,False, 0, 空的list [], 空的dict {}, 空的tuple () 以及空字符串 "" 都在某种程度上被认为是False。 比如x取值为上述任何一者的时候, not x 都等于 True。这两个是Python 2.5以后出来的新feature

basestring() 是str 和unicode的superclass

bin(x) 输出一个整数的二进制字符串。 比如 bin(9) = ' 0b1001'。 Python 2.6添加的很实用的一个功能。

bool([x]) 把一个值转换为bool值。规则如上在all, any中所述

callable(obj) 如果obj为可调用, 返回True, 否则为False。 比如 callable(lambda x: x**2) = True。 callable([1]) = False

chr(i) 将一个ASCII码转换为对应的字符。ord 为其反函数。 chr(48) = '0', ord('0') = 48。

cmp(x, y) 比较 x 和y, 如果xy返回正数

compile 编译一段python的code。比如 a = compile("print \'Hello World\', '', 'exec') 然后就可以用 exec(a)来得到'Hello World'的输出

complex 创建一个虚数

delattr(obj, name), setattr(obj, name) 比如 delattr(x, 'foobar') 等同于 del x.foobar

dict 创建一个dictionary。 类似用法的还有 tuple, list, set。需要提一下的是dict的用法。比如dict({'one':1, 'two':2})是最基本一种,实践中更加简洁方便的一种写法是 a = ['one', 'two']; b = [1, 2], dict(zip(a, b))。 zip是一个非常神奇的函数,用起来好处多多,可以让代码简洁清晰很多.

Friday, October 24, 2008

[SVN]设置ignore属性

1 设置本地,全局ignore属性
如果想在本地所有工作目录下屏蔽*.o, *.pyc这些临时文件, 可以修改"/etc/subversion/config" (针对所有用户)或是"~/.subversion/config"(仅针对当前用户):
添加, 或是去掉如下行的注释
[miscellany]
global-ignores = *.o *.pyc
这样不管在哪个工作目录, *.o 以及*.pyc都不会被列出来了.

2 设置server端,局部(每个目录可以不同)的ignore设置
进入你希望设置的工作目录,
svn propset svn:ignore "*.o" .
然后commit提交之后, 这个目录的svn:ignore属性便被设置成了*.o .

如果要同时设置多个ignore pattern, 比如 *.pyc *.pyd *.output的, 需要在不同pattern之间用回车隔开, 空格是不成的.所以可以用"\"符号输入多行
svn propset svn:ignore "*.pyc\
*.pyd \
*.o" .
或者写在文件里, 然后从文件导入:
svn propset svn:ignore -F .cvsignore .
或者调用外部editor:
svn propedit svn:ignore .

如果希望属性被递归的设置:
svn propset -R svn:ignore "*.o *.pyc" .

注意这个改动是server端可见的.也就是说别人的改动也会影响到你.

Tuesday, October 21, 2008

[Python]初探PyQt (1)

因为需要做demo的缘故,要搞一个GUI来显示一些东东。纯粹编程语言的话我肯定是首选Python。但Python的GUI编程我很不熟。很久很久以前用过tkinter来做,感觉不好,widget资源太少。最近用了很多基于Qt平台的东西,包括qterm,以及Python最强大的IDE eric。感觉Qt平台很漂亮资源也很丰富。所以就搞基于Qt的了。Qt是跨操作系统的一个图形界面平台,是挪威Trolltech 公司的产品。但是它提供免费的开源版本可以使用。著名的KDE桌面环境就是基于Qt开发的。Qt是使用C++的,可现在也有很多基于其它语言的binding(应该翻译成绑定么?),比如基于Python的PyQt和基于Ruby的RubyQt。PyQt就是我打算使用的。它允许我们在Python环境里调用Qt平台的API。

在Ubuntu上安装PyQt很简单,只要 apt-get install python-qt4就可以了。
在Mac上安装要稍微复杂一些,首先安装Qt4.你可以直接从源码安装,也可以port安装
port install qt4-mac
然后编译安装sip,最后才能编译安装PyQt

然后就可以上手了, 这里有一个很不错的PyQt的tutorial: http://zetcode.com/tutorials/pyqt4/。 同时你可以看到QtGui的所有widget: http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qtgui.html



QWidget(parent) 初始化控件时候可以指定该控件的parent.这样在parent被delete的时候,该控件也一同被delete
setGeometry(x,y,width, height). (x,y)是控件左上角坐标 -- (0,0)是左上角, width和height是控件的宽和高.
resize(width, height) 设定控件的大小
setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Raised) 设定frame周围边框样式
QtGui.QApplication.setStyle(QtGui.QStyleFactory.create('cleanlooks')) Typically they include "windows", "motif", "cde", "plastique" and "cleanlooks". Depending on the platform, "windowsxp", "windowsvista" and "macintosh" may be available.

(待续)

Sunday, October 19, 2008

[Linux]挂载ntfs分区

第一步,查看各个分区的UUID
sudo blkid
得到类似如下的输出:
/dev/sda1: UUID="B03459B334597CF2" LABEL="System" TYPE="ntfs"
/dev/sda2: UUID="CAEC3646EC362D57" LABEL="Data" TYPE="ntfs"
/dev/sda3: TYPE="swap" UUID="29e3c192-9a88-4304-be63-7ce425c5f0bc"
/dev/sda4: UUID="91c8e884-0927-4e5b-847e-383a5a7b4060" TYPE="ext3"
/dev/sdb1: LABEL="-----------" UUID="40DD-FB39" TYPE="vfat"
第二步,修改/etc/fstab:
# /dev/sda1
UUID=B03459B334597CF2 /mnt/winc ntfs uid=1000,gid=0,umask=000,nls=utf8 0 0
# /dev/sda2
UUID=CAEC3646EC362D57 /mnt/wind ntfs uid=1000,gid=0,umask=000,nls=utf8 0 0
这里设定可以在每次开机的时候将win下的c盘(/dev/sda1)挂载在我的/mnt/winc. 以后uid为我自己(1000是我的uid),gid为root. 其他参数还包括:
  • umask: 设定默认的文件以及目录的权限掩码. 4: read, 2: write, 1: execute. 000就代表给所有人(user, group, other)所有权限. 033的话就是给user rwx权限,group和other只有r权限.
  • dmask, fmask: 分别设定针对目录以及文件的权限掩码.
  • nls (native language support): 加入本地编码(比如我这里是utf8),这样就不会乱码.
事实上在linux下umask(或者dmask+fmask)的设定就是ntfs分区里所有文件目录的默认权限了.你用chmod去修改也不奏效.

Ref:
http://wiki.archlinux.org/index.php/Fstab_%28%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87%29

Thursday, October 16, 2008

[Linux]几个常用的Linux命令/工具的用法举例

这里是我平时常用到的几个linux命令以及比较trick的一些参数,附带简单的使用例子
文件操作

  • ls
    参数:
    • -h: 以人易读的格式显示文件大小 (比如 1K, 234M, 2G这样)
    • -R: recursively显示子目录下的文件
    • -t: 按修改日期排序(最近修改的靠前)

  • tar
    实例:
    • 例1:把foo这个目录打包并使用gzip压缩,并自动剔出.pyc文件以及version control的文件
      $tar -zcf foo.tar.gz --exclude '*.pyc' --exclude-vcs foo
    • 例2:把foo这个目录打包,但是用lzma压缩(lzma有比gzip的压缩比高,解压快的特点.但是压缩的时候慢)
      $tar -cf foo.tar.lzma --lzma foo
    • 例3:解压foo.tar.gz
      $tar -zxf foo.tar.gz
    • 例4:解压foo.tar.bz2
      $tar -jxf foo.tar.bz2
    • 例5:查看foo.tar.gz包内容
      $tar -tf foo.tar.gz

  • rm
    实例
    • 例1:删除一个叫--foo的文件
      $rm -- --foo
    参数
    • --: 删除以"-"开头的文件

  • find
    实例
    • 例1:找出$HOME 底下(recursively)所有以apc999开头的,owner为apc999的,permission为755的,创建时间为1天以前的文件
      $find ~ -name "apc999*" -user apc999 -perm 755 -mtime 1
    • 摆脱烦人的"permission denied"警告
      $find ~ -name "apc999*" -print 2> /dev/null 
进程操作

  • ps
    实例
    • 例1:显示当前终端的所有进程:
      $ps
      PID TTY          TIME CMD
      12713 pts/24   00:00:00 tcsh
      12840 pts/24   00:00:00 ps
      
    • 例2: 显示所有当前用户进程(包括使用了其他终端的) x, 显示进程的用户名 u,并用树型表示其父子关系 -H
      $ps ux -H
      USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
      apc999   12713  0.0  0.0  59732  1684 pts/24   Ss   15:11   0:00 -tcsh
      apc999   12839  0.0  0.0  74864  2080 pts/24   R+   15:20   0:00   ps ux -H
      apc999   12637  0.0  0.0  59732  1684 pts/10   Ss   15:07   0:00 -tcsh
      apc999   12760  0.1  0.0  24412  2052 pts/10   S+   15:13   0:00   top
      apc999   12821  0.0  0.0  66196  1144 ?        Ss   15:16   0:00 SCREEN top
      apc999   12822  0.1  0.0  24416  2048 pts/27   Ss+  15:16   0:00   top
      
    参数
    • u 显示进程的用户名
    • x 显示当前用户的所有进程(包括当前用户的其他终端)
    • -A (-e)显示所有进程(包括其他用户)
    • -U Username指定特定用户

  • screen 是一个窗口管理工具帮助你保持一个session在主机上的运行而不受外界因素影响.比如你ssh到一台主机上运行一个程序foo,当你ssh中断的时候, 这个程序foo的运行也将中断.为了让foo的运行不受ssh的影响,screen可以助你一臂之力.这里link是我写的比较详细的介绍
下载

  • wget其实是强大的下载/抓站工具,默认支持断点续传
    实例
    • 例1:将http://www.example.com/packages/foo.bar 下回来
      wget -r -c http://www.example.com/packages/foo.bar
    • 例2:将http://www.example.com/packages/ 下后缀为zip的文件(不包括子目录中的)全部下回来
      wget -r -np -nd -A.zip http://www.example.com/packages/
      把example.html中所有链接的zip文件下载回来, 只往下找一层
      wget -r -l1 -np -nd -A.zip http://www.example.com/example.html
    • 例3:下载urls.txt 中所有url:
      wget -i urls.txt
    参数
    • -r: 递归下载。如果是http的url,下载http文件当中超链接所引用的url;如果是ftp,下载目录(如同cp 或者scp 的-r参数)
    • -c: 指定断点续传。wget默认选项,只有该文件之前被其它ftp工具所下的时候才有用。
    • -np/-nd: 不在远端遍历父目录/不在本地建立目录结构
    • -l: 递归级数(配合-r使用)
    • -i --input-file: 下载在FILE文件中出现的URLs
    • -t: 重试次数
    • -A, --accept=LIST: 分号分隔的被接受扩展名的列表
    • -R, --reject=LIST: 分号分隔的不被接受的扩展名的列表

  • curl:一个利用URL语法在命令行下工作的文件下载或上传的工具
    实例
    • 例1:将http://www.example.com/packages/foo.bar 下回来,另存为a.bar
      curl -o a.bar http://www.example.com/packages/foo.bar
    • 例2:批量下载
      curl http://any.org/archive[1996-1999]/vol[1-4]/part{a,b,c}.html \
        -o "archive#1_vol#2_part#3.html"
      
标准输入输出上的文本处理

  • grep
    实例
    • 例1: 查找当前目录下所有文件(recursively)是否包含某一个正则表达式reg_exp,忽略大小写
      $grep -rin reg_exp *
    • 例2: 查找当前目录下所有以foo为extension的文件
      $grep -r --include "*.foo" reg_exp *
    • 例3: 显示匹配行以及上下两行的内容
      $grep -2 reg_exp *
    参数
    • -?: 显示匹配行的上下?行
    • -r: recursive 递归查找
    • -i: ignore case 不敏感大小写
    • --include: filename pattern 根据给定文件名pattern过滤
    • -n: line number 显示行号

  • awk: 在输入的文件或字符串中, 基于给定的规则提取文本.基本用法 awk 'pattern {action}'
    实例
    • 例1:将文件A.txt当中每行用,分割为若干个字段,输出第3个字段
      $awk -F "," '{print $3}' A.txt
    • 例2:检查哪个用户没有设立password
      $awk -F: '$2=="" {printf("%s no password!\n",$1)}' /etc/passwd
    • 例3:统计当前目录下所有.dat文件一共多大(对输入的某一列求和)
      $ls -l *.dat | awk '{ SUM += $5} END { print SUM/1024/1024 }' 
    参数
    • -F: 分割符
    • $1: 得到的第一个字段
    • $NF: 最后一个字段

  • cut: 和awk有一些类似,但用法比awk简单
    实例
    • 例1:将文件/etc/passwd当中每行用:分割为若干个字段,输出第1和第7个字段
      cut -d : -f 1,7 /etc/passwd
    参数
    • -b list: list指定第几第几个byte位置
    • -c list: list指定第几第几个字符位置
    • -f list: list指定第几第几个field位置

  • head/tail: head用来 显示一个文件开头部分, tail 显示一个文件结尾部分
    实例
    • 显示foo.txt的前100行
      head -n 100 foo.txt
    • 显示foo.txt的最后100个byte
      tail -c 100 foo.txt
    参数
    • -n: 行数
    • -c: 字节数
    • -f: 不结束, 不停刷新显示

  • tee: 很有用的小命令--把标准输出的内容复制到制定文件当中
    实例:
    • ls并把显示内容复制到ls_result 这个文件中。
      ls * | tee -a ls_result

  • uniq: 报告或者忽略输入中重复的行
    实例
    • 查看输入中有多少不同内容的行,以及每一行出现的次数
      cat foo | sort | uniq -c

  • diff: 比较两个文件或者目录下的不同
    用来比较两个目录(以及子目录)下文件的不同
    $ diff -r /path1/foo /path2/foo

  • hexdump: 报告或者忽略输入中重复的行
    实例
    • 把二进制文件foo按照16进制字符输出
      $ hexdump  foo 
      0000000 cf fa ed fe 07 00 00 01 03 00 00 80 02 00 00 00
      0000010 12 00 00 00 d8 08 00 00 85 00 20 00 00 00 00 00
      0000020 19 00 00 00 48 00 00 00 5f 5f 50 41 47 45 5a 45
      ...
用户相关的操作

  • adduser: 添加用户
    增加用户foo
    $ sudo adduser foo
    把用户foo添加到admin当中(可以sudo)
    $ sudo adduser foo admin

  • groups:查看某个用户所属的组
其他操作

  • time: 给命令计时. 注意有时候shell自带的time功能较弱,要用/usr/bin/time
    实例
    • 给命令cmd计时
      /usr/bin/time -f "%E" cmd arg1 arg2 

Tuesday, October 07, 2008

gedit的style以及语法增亮

(1) 用gedit 在Ubuntu上编辑Latex
现在很喜欢用gedit在Linux下面编辑Latex文档。它有一个非常好用的latex插件。Windows下面最常用的CTex/WinEdt套装里的基本功能这里也基本都有。说一下步骤:
  1. 虽然这个plugin不是默认的,但是只要下载下来然后把plugins/目录下的内容拷贝到 ~/.gnome2/gedit/plugins底下就可以了。
  2. Ubuntu默认的latex package没有装全,可以apt-get install texlive-full把所有的都拖下来。大概需要1G左右的硬盘空间
  3. 安装rubber: apt-get install rubber。 rubber是linux底下一个非常好用的latex编译工具。用来编译latex文档(足够次数以保证ref显示正确)
(2) 让gedit漂亮的显示code。
你已经可以用gedit来修改和编译latex文档了。但是gedit默认的color scheme对于latex的语法增亮支持的不好。事实上gedit 2.19以后的自定义color scheme功能使得用户可以把gedit的GUI和语法增亮设置到漂亮的发指的地步。当然也可以KUSO到发指。比如我就去下了一个Turbo Pascal/C界面的style回来,用起来及其怀旧。不过还是dark color的scheme好看以及省眼睛。自带的Oblivion就很好。 不过这个默认的scheme也对Latex的色彩增量支持不好。我又舍不得gedit的latex plugin。就决定自己动手丰衣足食,打造一个漂亮且对Latex,Python等code友好的color scheme。

相关知识:gedit的color scheme允许使用用户自定义的xml文件(当然它自己也带了4个风格,Tango,Oblivion等)。其色彩增亮依据的语法定义,借用了gtksourceview的一套东西。

第一步: 建立自己的风格定义文件。这里命名为APCDarkMate.xml。基本抄了DarkMate这个color scheme,增加了我自己的python和latex语法增亮:

<name="python:keyword" style="def:keyword">
<name="python:comment" style="def:comment">
<name="python:module-handler" style="def:keyword">
<name="python:builtin-constant" style="def:constant">
<name="python:builtin-object" style="def:type">
<name="python:builtin-function" style="def:function">
<name="python:boolean" style="def:constant">
<name="python:multiline-string" style="python:comment">
<name="python:special-variable" style="def:constant">
<name="latex:keyword" foreground="yellow">
<name="latex:common-commands" style="latex:keyword">
<name="latex:command" style="latex:keyword">
<name="latex:display-math" foreground="green">
<name="latex:include" style="latex:keyword">



(待续)

Sunday, September 28, 2008

[Python] 一些小tips

(1) 用isinstance判断变量类型
>>>A = [1,2,3,4]
>>>isinstance(A, list)


(2) sort, reverse 以及 sorted, reversed
A=[3,1,2]
assert(A.sort() == sorted(A))
assert(A.reverse() == reversed(A))


(3) 一个简单的命令行progress bar:
def progress_bar(current, total, width=20):
i = int (current*width/total)
sys.stdout.write("\r|" + '*'*i + ' '*(width-i)+"|")


(4) PyYaml最简单的用法
  • 把一个变量A dump到一个文件f中
    A = {1:'a', 2:'b'}
    yaml.dump(A, f)

  • 从外部yaml文件文件load出数据到A
    A=yaml.load(filehandler)
    


(5) 读取命令行的输入:
  • input(prompt)
  • raw_input(prompt)
  • import getpass
    getpass.getpass(prompt)

(6) 使用re正则表达式
import re
>>>m = re.match(r"(\d+)\s*(M|K)(bit|Byte)", "1024Mbit")
>>>print m.group(1), m.group(2)+m.group(3)
1024 Mbit

还可以使用(?P)来acess匹配到的字符串
m = re.match(r"(?P\d+)\s*(M|K)(bit|Byte)", "1024Mbit")
>>>print m.group("num"), m.group(2)+m.group(3)
1024 Mbit

为了提高使用正则表达式的效率, 可以先编译正则表达式, 然后每次用编译出来的正则字符串去匹配
>>>p = re.compile(r"(\d+)\s*(M|K)(bit|Byte)")
>>>g = p.match("1024Mbit")
>>>print g.group(1), g.group(2)+g.group(3)
1024 Mbit


(7)显示异常的类型和错误信息
try:
    do what you want
    except:
        print sys.exc_info()[0], sys.exc_info()[1]
sys.exc_info()[0]: 异常的类型
sys.exc_info()[1]: 异常的信息

(8) Python 2.5以后支持with 语句. 用在file object上,就不用close这个文件了
with open("max_load_vs_k.dat","w") as f:
    do some file operation with f


(9)Python Search Path
>>>sys.path
['', '/Library/Python/2.6/site-packages/ipython-0.10.1-py2.6.egg', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python26.zip', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/plat-darwin', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/plat-mac', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/plat-mac/lib-scriptpackages', '/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-tk', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-old', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-dynload', '/Library/Python/2.6/site-packages', '/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/PyObjC', '/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/wx-2.8-mac-unicode']

[VI]vim笔记

常用键
. 重复上一个命令
ctrl G 显示当前文件名等信息
去除^M %s/^M//g
^M = ctrl v+ ctrl M

移动
w,b 向右/左移动一个单词
ctrl f,ctrl b 向下/向上翻页
% 移动至匹配的括号
fc,Fc 向右/左移动至下一个字符c
tc,Tc 向右/左移动至一下个字符c

删除
dm 删除至移动指令m所到达的地方
di{, di} 删除当前配对的{}间所有内容
di(, di) 删除当前配对的()间所有内容


缩进
>> Indent line by shiftwidth spaces
<< De-indent line by shiftwidth spaces
5>> Indent 5 lines
5== Re-indent 5 lines
>% Increase indent of a braced or bracketed block (place cursor on brace first)
=% Reindent a braced or bracketed block (cursor on brace)
<% Decrease indent of a braced or bracketed block (cursor on brace)
]p Paste text, aligning indentation with surroundings
=i{ Re-indent the 'inner block', i.e. the contents of the block
=a{ Re-indent 'a block', i.e. block and containing braces
=2a{ Re-indent '2 blocks', i.e. this block and containing block
>i{ Increase inner block indent
<i{ Decrease inner block indent
Block Visual
ctrl+v 进入 Block Visual 模式;
用方向键控制在几行作业;
I 进入插入模式, 键入插入内容;
esc返回,这样插入的内容被应用于选中的每一行
d 删除选中的区域

如果发现无法实现上述功能,很可能是没有装完全的vim
在ubuntu或者debian下,可以

$ sudo apt-get install vim-full

编辑模式下使用上下左右键
:set nocp
或者在${HOME}/.vimrc中加入
set nocp

加密码
vim -x filename
更换密码:
vim +X filename

常用${HOME}/.vimrc的设置
  • set expandtab: 把tab置换为space
  • set ts=4: 设置tabstop为4
  • set tw=0: 设置textwidth。 一行长度超过textwidth的时候会添加line break。为0的话disable这个功能
  • set showmode: 显示当前vi工作在什么模式下
  • set nocompatible: 抛弃和vi兼容性.通常如果在插入等模式下用方向键出来ABCD之类的字母,就这样设置
  • .vimrc中, 如果要注释一行,使用双引号"


打开多个文件和在其中移动
使用tab (http://vim.wikia.com/wiki/Using_tab_pages)
  • :tabe filename 在新tab中打开另一个文件
  • :tabs 查看所有tabs
  • :tabc 关闭当前tab
  • :tabc {i} 关闭第i个tab
  • gt 上一个tab
  • gT 下一个tab

切割屏幕
:split
:split filename
:vsplit
:vsplit filename
在窗格间切换
ctrl-W 上/下


VIM Quick Reference
VIM tips and tricks

Friday, September 12, 2008

[Python]用Pylab给Paper画图

之前写paper 画图一般都用Matlab画图。因为Matlab的plot可以生成eps格式的图片。但是最近都是用Python的pylab包来画图。原因是一般用在paper里的eps文件插在paper里通常都显得字比较小,需要调整线宽和字体大小。手动在matlab的figure编辑界面里自然可以修改,但每次都要做同样的工作非常令人厌烦。或者可以在matlab画图的源文件里加上比如 plot(...., "linewidth", 2)之类的语句, 但是当画图的语句一多起来,这样也很麻烦。所以我觉得用pylab来画图更加方便。pylab的绘图语句和matlab有高度的兼容性。另外python强大的文件处理和字符串处理能力正是matlab的软肋。

使用pylab画图的时候, 可以事先用 rcParams 来改变默认的线宽、图例的字体大小、x,y轴的label和tick的字体大小。

rcParams['lines.linewidth']=2
rcParams['legend.fontsize']=16
rcParams['axes.labelsize']=14
rcParams['xtick.labelsize']=14
rcParams['ytick.labelsize']=14

后面就用普通的plot函数(用法和matlab一样)来画图。再有就是可以用savefig来直接存成eps文件。

Friday, September 05, 2008

[Python]用Python开发Firefox扩展:1 准备工作

- 准备好你的Firefox
既然是为Firefox做extension,自然少不了用Firefox来调试啊之类的。这样也免不了把它弄崩溃。呵呵 我还在试验helloworld的时候就把Firefox弄得无法启动了。其实Firefox非常体贴的提供了多profile启动的功能。用
firefox   -ProfileManager
来启动,这样可以添加、删除firefox的profile。平时我们用的都是default的profile。我们就可以添加一个dev的profile。这样启动的时候firefox会提供选择使用哪个profile。所有对firefox做出的更改,比如字体啊,插件啊,扩展啊,都是限定在你使用的profile内。所以一旦调试的时候出了问题,我们只需要删除相应的profile就好了而不会影响平时的上网和使用。

Firefox的Profile 文件依据操作系统不同而处于不同的路径下,具体可以参见这里

- 编译PyXPCOM
有关编译PyXPCOM请参见这里. 简单说来,你需要从源码编译mozilla套件(而不仅仅是 Firefox)。编译的时候需要在makefile里加入相对应的选项 (ac_add_options --enable-extensions=python/xpcom,default)。做好准备:编译需要很长时间,你可以睡觉前开始。

Friday, August 29, 2008

[Python]IPython: Python与Shell的混血王子

无聊的时候试用了IPython便爱不释手了。IPython是一个增强版的Python解释器。你完全可以把它就当作python的解释器来用--没有问题。但它的好处是内置了很多类似linux shell的特性。我觉得对我来说很实用的包括以下这些:
  • 比如可以在IPython里使用ls, pwd, mkdir这些命令而不用先import os 再来os.system("ls")
  • 对于那些没有内置的linux命令及工具,可以用!cmd 或者!!cmd 来调用。就如同在vi里调用外部命令一样
  • 可以用?modulename来查看一个module的用法和结构,相当于help(modulename)的简写了吧
  • 支持使用tab键来补全命令
  • 可以使用用%run filename args来load并执行一个外部py文件。就如同在shell里执行python filename args
  • 可以debug python脚本
以上这些是把IPython作为python解释器(默认的profile)的用法。实际上还可以更夸装一点: ipython -p pysh 来启动IPyhton。 这样默认相当于进入了一个Shell 从而不用!或者!!来调用命令。同时你还具有Python的那些模块和数据结构可以使用。比如你可以使用如下的程序来做找出当前目录下所有的.py文件并生成同名的文件夹(没有扩展名.py):
files=!ls
for f in files:
    if f.endswith('.py'):
        mkdir ${f[:-3]}

Monday, August 11, 2008

bibtex的crossref,以及winedt的自定义按钮

(1)问题: bib文件当中使用了 cross-refs 。比如所有的sigcomm2008的引用就被cross-ref到一个sigcomm2008的entry当中,这样就不用每个都分别输入address, year, booktitle了。但是带来一个小问题,如果实用超过1个这样的cross-ref,比如sigcomm2008和sigmetrics2008,那么第二个就会被单独编译成一个ref,比如[1] sigmetrics 2008, xxxxxx。

解决:bibtex 有一个选项-min-crossrefs 默认值为2。所以编译的时候可以加入选项把这个值调大,比如1000

(2)问题:winedt当中调用bibtex的时候如何打开上面所说的选项。

解决:
Options -> Execution Modes, Accessories 栏里, 选择Bibtex,然后command line里面的Switches里加上这个option : -min-crossrefs=1000。 实际上这里就是设定latex编译时的各个参数。另外可以改成Batch方式,这样就不是直接调用这些命令,而是使用 CTeX\WinEdt\Bin\TeX 这里的对应的批处理文件。从而可以进行更复杂的处理

(3)问题:winedt是一个很好的tex编辑器,可是生成了pdf文件以后(比如使用的是pdftex),默认的浏览方式是调用adobe acrobat, 灰常消耗资源. 想要换成调用foxit reader来打开生成的.pdf文件。

解决:
Options -> Menu Setup, 在main menu里面选择Items -> Accessories,双击。打开了Accessories菜单的定制面板。在&PDF 条目下添加&Foxit Reader。对应的Macro处填上,b\Exec\FoxitReader.edt'); 如右图所示。我还抓下了foxit reader自己的icon然后添加过来的。(考察WinEdt-Large.btn 和WinEdt.btn)
然后在 CTeX\WinEdt\Exec目录下创建 FoxitReader.edt。 我的这个文件很简单,就是:
Run('"Foxit Reader" %P\%N.pdf ','%P',0,0,'%N.pdf - FoxitReader',1,1);
End;
保存后,就可以从菜单中选择用foxit reader来打开了。这里我的foxit Reader已经添加到PATH当中了。如果不想添加,可以使用foxit reader的全路径。如果嫌麻烦还想创建工具栏按钮来打开。可以在工具栏上右键, 选择enter toolbar setup。然后拖拽按钮到工具栏上。就可以从工具栏上快速的启动foxit了

总结: WinEdt有着强大的自定义工具以及一套强大的宏。不过菜单和界面实在做的让人有点匪夷所思。常常不知道需要的功能在哪里。 比如Options菜单里,同时有setting,preference,setup 和configuration。实在能把人给绕晕了。

一霸阿,居然发现这里还有个很久以前的blog

呵呵,以后技术类的东西往这里贴了,
生活里的东西写在MSN Space里面 。

MSN Space对Firefox的支持太差了,
算是我放弃(partly)它的一个主要原因吧。