Archive for the 'C-Tips' Category

phdfs.py, a ctypes wrapper of hadoop libhdfs for python

Saturday, May 10th, 2008

I use python and hadoop distributed file system (HDFS) to process large amount of data at work. Instead of using the regular map-reduce mechanism provided by hadoop, I have my home-made map-reduce python engine written using Pyro. It turns out it is quite efficient and sometimes it is much faster than the corresponding streaming code for some simple map-reduce work. For this kind of work, I access the file in HDFS using “hadoop fs -cat” by the unix pipe (popen) in python. It seems to me it might be useful to be able to bypass the somehow ugly unix pipe and “hadoop fs -cat” combination. There already is a SWIG wrapper of python for hdfs. However, I think it will be nice to have ctypes wrapper such that no extra compiling is necessary for installation. I spend a few nights working on such wrapper and hope it will be useful. The results is a single python module that I call “phdfs“. It provides most of the API in the libhdfs. It will be useful if one want to read, write and manipulate the hadoop filesystem with the flexible and powerful python syntax.

You can download the phdfs.py, and try it out yourself. I have not tested all the methods, so YMMV.

Using Safari on iPhone to read CHM file

Sunday, September 23rd, 2007

iPhone is a fancy toy with a lot of power but Apple deliberately locks a lot of the potential power. One thing I like to do on an iPhone is to be able to read CHM files. As a weekend project, I setup the tool chain for iPhone following the instructions. Then, I grabbed the source code of chmlib. With some minor modification, I was able to compile the chmlib as an iPhone binary library. That was very encouraging.

This provides a convenient way to make iPhone as a CHM reader. In the chmlib source code distribution, there is an example program that runs as a http-server that serves the content of a CHM as standard web page. The “mobileSafari” has no problem to render the results, but the fonts are usually too small to read and the text is typically rendered too wide such that a lot horizontal scrolling becomes annoyingly necessary.

I decided to combine some python code with the chm_http server from the chmlib source code. I modified the source code of chm_http so it can call python code to modify the HTML code in the CHM file, replacing the original CSS with new setting for reading on small screen. Furthermore, I found it was tedious to start the chm_http from a terminal every time when you want to read a different book. I wrote another small python script that can scan a directory and find all CHM files in the directory to output an index html page. At the end, I was able to use the mobileSafari pointing to the index page and select the book I want to read. The “chm_http” server would start automatically to get the book I like to read.

If you are interested in reading CHM on your iPhone. Get this iphoneCHM.tgz (the file would be upload soon). Copy the “chm_http2“, “rewriteHTML.py“, and “CHMServer” to “/usr/local/bin/” in your iPhone. Change the permission of these files such that you can run all of them. Put some chm files in /var/root/Media/CHM_Ebooks/. Open a terminal in the iPhone or ssh into the iPhone to run “CHMServer”. After that, ask the Safari to open this URL http://127.0.0.1:8000. You should see the links to the CHM files. You can now click on any of them and enjoy a nice reading time.

Technorati Tags: ,

用 python+OV 寫中文輸入法

Wednesday, July 18th, 2007

前一陣子看到 lukhnos 在寫一個能讓 OV 用 Ruby 來寫 filter 的模組,一時心血來潮想看看如何用 python 來寫 OV 的 filter 的模組。花了點時間研究了一下如何在 C/C++ 中內藏 python。 雖說用 python 來寫程式作研究也有好一陣子,也曾經用過 SWIG 來控制用 C/C++ 寫的物理模擬程式, 在 C/C++ 中呼叫 python 倒是第一次實做。花了點時間寫了個 prototype,在 lukhnos 的協助下,搞定了一個讓 OV 可以用 python 寫 filter 的模組 (在 OV 的 svn repository: Modules/OVOFPythonBased/ 中)。

OV 的 filter 主要是呼叫一個叫 process 的 method。傳到 process 中的只是一個字串,所以實做 OV 的 filter 並不是太難。發展的過程中,大多數的時間花在看 python 的 C API 文件,熟悉如何在 C/C++ 中建立 python 的物件及將參數傳給 python 的 method。

讓 OV 的 filter 機制可以用 modern 的 python 或是 ruby 實做只是第一步。Dynamic language 的方便已經讓發展新的 filter 的工作大大的簡化。所以下一個就是看看能不能讓 OV 用 Python 或是 Ruby 來寫輸入法。在未來實驗類似酷音等比較複雜的自然語言處理的輸入法模組的時候,如果可以用 Python 或是 Ruby 來寫輸入法應該會有很大的助益。

寫 python based OV filter 時, 只需要定義好對應到 process 的 python method/function 就好了,python 的部份是完全的被動,python 的 code 並不需要管 C/C++ 的 class 與 instance,只需要實做一個叫 process 的函數就可以了。 但寫 OV 的輸入法模組的時候,有幾個 OV 的物件必須要傳到 Python 中,而且 Python 也最要能夠 subclass OV 中的 class 來保持 OV API 介面的一致。基本上要做下面幾件事:

(1) 用 SWIG 來把 OV 的 class 轉成 Python 的 class。
(2) 定義對應到 Python class 的 OV C/C++ class。
(3) 在 (2) 中最重要的一件事就是要把將 OV C/C++ 中 instance pointer 轉成 Python 可以認得的物件。

在這三項工作裡,最容易的部份是 (1)。基本上只要把 Framework/Headers/OpenVanilla.h 剪貼到 SWIG 的 interface 檔中就好,唯一要注意的地方是要讓 SWIG 知道要將 C++ 的 class 轉成 python 的 class。這要用到 SWIG 中的 directors 。請見 SWIG 的相關文件Modules/OVIMPython/ 中的 OVIMPython.i

接下來要就是要讓 OV C/C++ 知道 Python 的存在,主要要去 subclass 兩個 OV C/C++ 的 class, OVInputMethodContext 和 OVInputMethod, 讓 OV 的 loader 可以呼叫對應的 python 物件。請見 Modules/OVIMPython/OVIMPythonBased.cpp 中的 OVIMPythonBasedContextOVIMPythonBased class。 這兩個 wrap classes 作的事情很簡單,就是實做 C++ method 來呼叫對應的 Python instance method。但是之前的一個障礙就是 OVInputMethodContextOVInputMethod 中的 method 的參數裡大多是指向 C++ 的 instance 的 pointers。要怎麼把這些對應的 instance 變成 python 物件在傳給 python 倒是一個比較不容易的問題。也牽涉到 SWIG 怎麼把 C++ 物件映射到 python 物件的細節。

也許在 SWIG 有對應的解法,但我並沒有從 SWIG 的文件中看到顯而易見的方法來解決這個問題。後來是在研究 SWIG 產生的 python module 的檔案中找到 hint。對每一個要 wrap 的 C++ class,SWIG 會產生兩個對應的 python class。例如如果在 C++ 中有如下的宣告:

class OVKeyCode : public OVBase  {
public:
    virtual int code()=0;
};

SWIG 會建立下面兩個 python class:

class OVKeyCode(OVBase):
   ...

class OVKeyCodePtr(OVKeyCode):
   ...

其中 OVKeyCodePtr 的 constructer ( __init__() in python ) 可以用 SWIG 中的表示 C/C++ pointer 的 python pointer object 建立對應的 python object。所以接下來要作的就是要把 C/C++ 的 pointer 轉成 python 中 pointer object。而 SWIG 的作法只是把 C/C++ 中的 pointer 的 address 和 type 換成特殊格式的字串,在 SWIG 所產生的 C/C++ 的 wrap 檔中有一個特別的函式 (char *SWIG_PackData(char *c, void *ptr, int sz) ) 就是把 C/C++ 的 pointer 換成字串,所以我們就可以用這個函式將 C/C++ 的 pointer 轉成對應的 python 字串然後透過 SWIG 產生的 aClassPtr 來產生 python 中的 aClass 的 instance,而這個 python instance 的 implementation 就是對應的 C/C++ implementation。

這樣的 mapping 實在有點太複雜而不直覺。還沒有真的詳讀 SWIG 的文件,不知道有沒有比較優雅的方式來作同樣的事。雖說如此,對要用 python 寫輸入法的人可以完全不去理 wrapper 本身及兩個語言的物件對應的複雜性,專注在用 python 來寫輸入法。 在lukhnos 稍早寫的用Python + OpenVanilla寫輸入法中有用 python 的 OV 輸入法的 minimum example。

我想這只是第一步,我自己來試著了解 embedding python 的小小練習。如果有空的話,再看看如何真的用 python 在 OV 裡作些有趣的事。

Circular references in python

Sunday, June 24th, 2007

The following code create circular references in python:

>>> aRef = []
>>> aRef.append(aRef)
>>> print aRef
[[...]]

This creates a list object referred by a variable named “aRef”. the first element in the list object is a reference to itself. In this case, the “del aRef” dereference aRef to the list object. However, the reference count of the list object does not decrease to zero and the list object is not garbage collected, since the list object still refers to itself. In this case, the garbage collector in Python will periodically check if such circular references exist and the interpreter will collect them. The following is an example to manually collect the space used by circular referenced objects.

>>> import gc
>>> gc.collect()
0
>>> del aRef
>>> gc.collect()
1
>>> gc.collect()
0

Technorati Tags:

Compress Canon A620 AVI and DV to H.264 mp4 file

Wednesday, May 31st, 2006

Just a memo for myself.

With mencoder, mplayer, ffmpeg and mp4box, I can finally reduce the size of the video files created from my Canon A620 to reasonable sizes such I can put them in my powerbook without depleting the hard drive space.

This is the script for converting AVI to mp4,

mencoder $1 
-ovc x264 -nosound -ni -sws 0 -x264encopts 
threads=1:me=2:qp_min=22:
qp_max=51:i4x4:keyint=120:nocabac:deblock:nob_adapt 
-ofps 29.97 -vop harddup -of rawvideo 
-o $1.264

mplayer -vc dummy -vo null -ao pcm:file=$1.wav $1 

ffmpeg -i $1.264 -i $1.wav -y -vn -f mp4 -acodec aac 
-ab 96 -ar 11025 -ac 2 -map 1.0:0.0 $1.aac.mp4

MP4Box -fps 29.97 -add $1.264 -add $1.aac.mp4 -new $1.mp4

rm $1.wav
rm $1.264
rm $1.aac.mp4
touch -r $1 $1.mp4

For convert DV to mp4, I use

ffmpeg -i $1 -y -vcodec h264 -f mp4 -acodec aac 
-deinterlace -b 1280 -aspect 4:3 -s 640x480 -naq 
-parti4x4 -deblock -copyts -keyint_min 120 -h264 1 
-mv4 1 -bf 2 -coder 1 -parti4x4 -partp4x4 -parti8x8 
partp8x8 $1.mp4touch -r $1 $1.mp4

The results seem pretty reasonable good, while the sizes are still under control.

Open firmware password and firewire enclosure

Tuesday, January 31st, 2006

I have a firewire enclosure using Genesys GL-711 chip. It has been working well. However, I tried to mount it under OS X.4.4 earlier today and failed. The System Profile showed the firewire bus but not the hard drive. My powerbook could still mount other external firewire hard drives using different chipsets and the GL711 box could also work with other computer too. I was very puzzled.

I tried to reset PMU and zapped PR ram. I needed to disable the open firmware password to do so. After the zapping PR-ram, resetting PMU, rebooting the computer, the hard drive controlled by GL-711 showed up. I thought it might be a good idea to set the password again, so I did it. Reboot, the powerbook could not see the hard drive anymore. After a few more rebooting and testing, I confirmed that setting open firmware password affected whether the powerbook 12 inch could see the hard drive or not.

This is such strange bug. How would the open firmware password affect the firewire bus? And why it is so specific to one kind of firewire bridging chip but not the others? I guess it would probably not be easy to figure that out.

Safe Sleep

Monday, November 14th, 2005

In the recent OS X 10.4.3, it is possible to “suspend” my powerbook into hibernate mode that does not use any power (see Andrew’s Blog). I write this simple script “sleepmode” to make life slightly easier with this feature.

#!/bin/sh
case ”$1” in
  deep)
    sudo pmset -a hibernatemode 1
  ;;
  safe)
    sudo pmset -a hibernatemode 3
  ;;
  normal)
    sudo pmset -a hibernatemode 0
  ;;
  go)
    omode=”`pmset -g | grep hibernatemode | cut -f 2`”
    sudo pmset -a hibernatemode 1
    echo The system is going to the deep sleep in 3 seconds
    sleep 3
    osascript -e 'tell application "Finder" to sleep'
    sudo pmset -a hibernatemode $omode
    echo The system is back to it orginal sleep mode
  ;;
esac

case ”`pmset -g | grep hibernatemode | cut -f 2`” in
  0)
  echo System is in the Normal Sleep Mode
  ;;
  1)
  echo System is in the Deep Sleep Mode
  ;;
  3)
  echo System is in the Safe Sleep Mode
  ;;
esac

看看上個星期收集了多少和那些垃圾, Tiger’s Way

Wednesday, October 5th, 2005
mdfind -0 -onlyin /Users/ "kMDItemUsedDates >= $time.this_week(-1)" |
 xargs -0 du -k |
 sort -k 1 -n -r

當然,你也可以用 SmartFolder.

看看上個星期收集了多少和那些垃圾

Tuesday, October 4th, 2005
find  .  -newerct  '7 days ago'  -exec ls -ald {} ; > fileList

小心 “.

Thursday, September 29th, 2005

最近學校的電腦有幾台使用者不管的電腦有個使用者的密碼被猜到,侵入的 angelbot 用 ssh 登錄,然後會載入一堆針對 linux 中許多程式的漏洞來攻擊的程式取得 root 權限,然後會再去掃描其他電腦的 ssh 的 user/password 組合。這個 bot 應該是可以從遠端 irc 中控制。

如果發現系統中,有個 angel 的帳號的話,那就是中獎了。這個 bot 藏在 /var/tmp 的一個目錄,這個目錄名是 “. “,所以不小心看,會以為這是 “.” 目錄,要進這個目錄,要 ‘cd “. /”‘。進去後會有一堆 cracker 用的工具。

不要有亂七八糟的使用者帳號,沒事去看看 /var/log/auth.log 或是 /var/log/secure,如果被入侵了,記得把 “. ” 擦乾淨。

(另一個 angelbot 的 trace 是這個 bot 會跑一個叫 “[httpd]” process 來跟遠方的 bot 透過 port 8888 眉來眼去。不注意看的話也是很容易漏掉。)

Debian linux as a VPN server for OS X

Tuesday, September 27th, 2005

最近決定來試看看把在學校裡工作用的 desktop 拿來當自己的 VPN server,這樣作最大的好處是可以在家裏工作時還是可以取用學校有訂閱的期刊論文的電子版。雖然學校其實有提供 VPN client 連到學校的 VPN server,但是好像還不支援 Tiger,要多裝一個 client 也是很煩的事。之前我是用 ssh tunneling 加上 tinyproxy 來『模擬』VPN,其實也已經很實用了。但是還是手癢,想來玩玩自己的 VPN server 然後用 Tiger 內建的 VPN client 去連結。

在 Tiger 可用的而 linux 有支援的 VPN 中,pptp 是最好設定的。在 Debian 下唯一比較麻煩的是要自行編譯 ppp_mppe.ko 的 kernel module。把 ppp_mppe.ko 編好後,在 /etc/modutils/aliases 中加入一行

alias ppp-compress-18   ppp_mppe

這樣 kernel 才會自動載入這個 module,當然妳也可以用 insmod 來載入所有 ppp_* 相關的 module。

要把 debian 設成 pptp 的 server 要先用 apt-get 安裝 pptd 套件:

apt-get install pptpd

然後再來要設定下面幾個檔案,

設定 pptp:

file: /etc/pptpd.conf 

speed 115200
option /etc/ppp/pptpd-options
noipparam
logwtmp
bcrelay eth0
localip 192.168.0.1
remoteip 192.168.0.234-238,192.168.0.245

設定 ppp:

file: /etc/ppp/pptpd-options

name pptpd
ktune
refuse-pap
refuse-chap
refuse-mschap
require-mschap-v2
require-mppe-128
# replace 127.0.0.1 with the remote server's DNS ip
ms-dns 127.0.0.1
proxyarp
nodefaultroute
lock
nobsdcomp
nodeflate

設定用戶代號與密碼:

file: /etc/ppp/chap-secrets                              

# Secrets for authentication using CHAP
# client        server  secret                  IP addresses
VPNUserName pptpd VPNPassword *

把 ppp 連結的 traffic 導向到 server 的外部 ip/網路卡:

file: /etc/ppp/ip-up.local 

#!/bin/sh
echo 1 > /proc/sys/net/ipv4/ip_forward
modprobe ipt_MASQUERADE
iptables -t nat -F
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

這些設定完成後。在 OS X 下就可以 Internet Connector 中的 PPTP VPN 來連到 server 上。記得要把 Internet Connector 的選單中 Connect -> Options 中的 Send all traffic over VPN connect 選起來。這樣再加上在 server 上的 iptable 的設定,當用 VPN 連線的時候,外界看起來就像你是從 server 連出去的(妳可以試著連到 checkip.dyndns.org 來看看外面的網站看到的 ip 是不是 server 的 ip)。

在 Aquamacs 用中文的小訣竅

Sunday, September 4th, 2005

在 Mac OS X 上的 emacs 正如其他 Unix 裡的 emacs 一般有很多不同的版本。以前用的是 Carbonize 的 emacs,要在上面設定使用 utf-8 的正體中文總是對 .emacs 動不少工程,甚至必要的時候,還得自行從原始嗎加上補丁重新編譯。

Aquamacs emacs 是在 Mac OS X 上 Aqua 化的 emacs,所以就 GUI/字形來說,會比別的建立在 Carbon 及 Terminal 上的 emacs 來得自然。但是我以前試驗過早期 Aquamacs 的版本不夠穩定,所以我一直是使用自己編譯的 Carbonize emacs。不過,最近一版的 Aquamacs 相當不錯,加上要在其中使用,utf-8 中設定相當方便,試驗中文成功後,我就把自己編的 Carbonize emacs 給砍了。

要在 Aquamacs 下使用 utf-8 的正體中文只需在 ~/Library/Preferences/Aquamacs Emacs/Preferences.el 中加上兩行,

(set-language-environment “Chinese-Big5″)
(prefer-coding-system ‘utf-8)

就可以用中文了。

Auqamacs 中也正確處理了剪貼簿中的編碼,不需要任何特別的設定,不管是那種 encoding,都可以在 Aquamacs 與其他的 OS X 軟體中自由的剪來貼去了。

有需要在 OS X 下中用 emacs 的朋友不妨試試 Aquamacs,說不定您會像我一樣,覺得 Aquamacs 還滿合用的。