04 8月 2011

[Python] Lazy initialization

在寫大型的Project時,應該都會遇到一種痛,就是AP開起來的速度"操級慢",很多人習慣在一開始就把一些用不到的變數initial起來,不但影響到AP launch的速度,也會讓memory吃得肥茲茲的。

所以就有人嘗試在一開始將變數initial成None,等到要用時再判斷是不是None,是的話再真正的initial這個變數。

不過這種作法,可能會讓code變得稍微複雜一點,參考一下別人的作法,其實有更好的方法來實作這種Lazy Initialization,就是用到Python的decorator+property!

12 4月 2011

[Python] 取得Python object的reference count

在Python的世界裡,每個變數都是一個object,而且每個object會有一個reference count去記錄被reference幾次,一但這個值變0時,這個object才會真正被delete掉。

[Python] 實作一個PriorityQueue 與 有pause, resume 功能的PriorityTaskThread

由於project是用Python2.5,要用到PriorityQueue,但是Python2.6以後才支援PriorityQueue,所以就想說寫個來試試。主要是改寫自Python原有的Queue class,繼承了原有的access blocking的feature,將原本的put改用insert與append,讓有相同priority的task能有先後之分。

07 4月 2011

[Python] Hook stdout後 print會出現 UnicodeDecodeError

在Python裡,字串的表達方式分為兩種,一種是常見的ansi string:"abc",另一種則是unicode:u"abc",而OS在秀出文字到window上時,其實都會轉換到使用者設定的code page後才秀出來的。簡單來說,繁體中文有一個對應的code page(cp950),簡體中文也有個對應的code page(cp936),如果一個unicode的字串參考錯誤的code page轉換出來的字串就有可能會變成亂碼了。

22 12月 2010

[emomeDDSMS] 下載emome上的備份簡訊 更新0.73

應觀眾要求,新增功能,輸出傳送簡訊的號碼與通訊錄的暱稱。
下載連結(按右鍵另存新檔):emomeDDSMS 0.73 (2010/12/22)
Change Log:
1. Add output phone number and nick name function - GetPhoneBook() and ConvertPhonelist()

使用說明,請參考前一篇文章。

28 9月 2010

[emomeDDSMS] 下載emome上的備份簡訊 更新0.72

因應emome網頁些許的更新與問題,emomeDDSMS也要稍作修改。
下載連結(按右鍵另存新檔):emomeDDSMS 0.72 (2010/9/28)
Change Log:
1. emome browse sms page changed, 'from' action changed to 'POST', modify related url actions.
2. Add ResetPage() mechanism for emome website issue, sometimes can't browse normal
3. Add description, suggest to download file to D disk

使用說明,請參考前一篇文章。

12 5月 2010

[SudokuBoxer] Project 轉移至 SourceForge

一開始將 Project 放在Google code,連線至SVN的速度還不錯,介面操作很陽春,但是也很方便。不過使用了一陣子後,發現放在上面供人下載的檔案,下載次數有著砂鍋大的問題,不管下載幾次,次數都不會增加,這樣子的結果實在令人傷心…到Google code的論壇發問,才知道原來這個 issue 已經 create 出來很久了,早在2009/12時就已經存在了,但是到現在還沒修好,這效率著實令人吃驚。

所以,才將 Project 轉移至 SourceForge,應該是之前有開過 Project 的關係,開新 Project 時也不需要審核,而且開新 Project 的步驟與介面也不像之前讓人退避三舍。上傳檔案的部分也有很大的進步(以前一定要在command line底下上傳才行),現在只要在網頁上東按西按就可以上傳了。重點是 Download 次數的統計實在比Google code來得好多了。

有興趣的人可以下載來玩玩,更新了不少東西  :)


25 3月 2010

[SudokuBoxer] wxPython 實作Sudoku GUI Game

前一陣子利用空閒時間練習了一下wxPython,順便寫了一個Sudoku的小遊戲,想說完成的話,可以給我媽玩一下。

目前的功能還很陽春,不過至少題目的難易度滿正確的,在產生正確的題目上費了不少功夫,曾經嘗試過連到某Sudoku網頁去解析題目網頁的html語法,然後再儲存到DB裡,可是這招實在是太sucks了,抓不到50題,就被擋IP了 XD (看來是sleep的間隔時間不夠長.... ) 後來還找了一些tool來產生題庫,但是效果都不盡理想,不是題目有問題,就是題目難易度不均。

後來終於找到一個 Sudoku 產生題庫的 tool,跟一個可以幫題目打分數的 tool。雙管其下的結果還算讓人滿意。


Sudoku Importer - 以挖洞法產生sudoku題庫,所以必須餵入題目挖洞的template
Sudoku Explainer - 一個強大的Java GUI Sudoku軟體,可以教你怎麼一步步解題,以及解題所需要的技巧,最重要的是可以餵給它題目,然後產生該sudoku的難度分數以及解題所需要的技巧。
改天再寫一篇介紹怎麼用這兩個 tool 吧。


SudokuBoxer遊戲畫面

SudokuBoxer是用wxPython實作的,可惜的就是執行檔大了一點, 壓縮完後竟然還要5MB,沒壓縮也要15MB,真是誇張。

這也是我第一次用wxPython,第一次自己動手用 gettext 作 Multi-Language,程式還有很多功能沒完成,不過應該是不會輕易當掉啦,呵。想說弄到一個段落就放上來Share給大家一下。Python上手後,真的是快速開發的好物啊!

可惜 wxPython(wxWidgets) 在繪圖上的功能過於陽春,連 Texture 之間的 Alpha Blending 功能都沒有,不過wxWidgets可以貼OpenGL的Canvas上去,應該可以補足這一塊,但還要花時間學OpenGL就是了,大學學過都還給老師了....

22 3月 2010

[emomeDDSMS] 下載emome上的備份簡訊 更新0.71

因應emome網頁些許的更新,emomeDDSMS也要稍作修改。
下載連結:emomeDDSMS 0.71 (2010/3/21)
Change Log:
1. Modify login.js path in Login()
2. Modify @name to @user_name, because unknow Chickenfoot issue to use parameter @name.

使用說明,請參考前一篇文章。

26 2月 2010

[wxPython] 實作多國語言MUI by GetText

wxPython提供了方便的支援多國語言API,結合GNU GetText project,使用上很是方便。
由GetText parse 檔案後,建出PO檔然後轉成MO檔,就可以給wxPython讀取使用。

22 12月 2009

[Windows] Local time 轉 UTC

Window提供了 API 可以轉換時間的時區。
  • TzSpecificLocalTimeToSystemTime:Local time -> UTC
  • SystemTimeToTzSpecificLocalTime :UTC -> Local time
第一個參數可指定 TIME_ZONE_INFORMATION,如果傳進 NULL 的話,即代表目前系統使用的Time Zone。

    SYSTEMTIME ConvertLocalTime2UTC(UINT year, UINT month, UINT day, UINT hour, UINT minute, UINT second)
    {
        SYSTEMTIME local, utc;
        ZeroMemory(&local, sizeof(local));
        local.wYear   = year;
        local.wMonth  = month;
        local.wDay    = day;
        local.wHour   = hour;
        local.wMinute = minute;
        local.wSecond = second;
        TzSpecificLocalTimeToSystemTime( NULL, &local, &utc );
        printf("UTC Time  =%d/%d/%d %d:%d:%d\n", utc.wYear, utc.wMonth, utc.wDay, utc.wHour, utc.wMinute, utc.wSecond);
        printf("Local Time=%d/%d/%d %d:%d:%d\n", local.wYear, local.wMonth, local.wDay, local.wHour, local.wMinute, local.wSecond);
        return utc;
    }
    
    SYSTEMTIME ConvertUTC2LocalTime(UINT year, UINT month, UINT day, UINT hour, UINT minute, UINT second)
    {
        SYSTEMTIME local, utc;
        ZeroMemory(&utc, sizeof(utc));
        utc.wYear   = year;
        utc.wMonth  = month;
        utc.wDay    = day;
        utc.wHour   = hour;
        utc.wMinute = minute;
        utc.wSecond = second;
        SystemTimeToTzSpecificLocalTime( NULL, &utc, &local );
        printf("UTC Time  =%d/%d/%d %d:%d:%d\n", utc.wYear, utc.wMonth, utc.wDay, utc.wHour, utc.wMinute, utc.wSecond);
        printf("Local Time=%d/%d/%d %d:%d:%d\n", local.wYear, local.wMonth, local.wDay, local.wHour, local.wMinute, local.wSecond);
        return local;
    }

    Reference:

    12 12月 2009

    [Win32 API] String Conversion

    在Windows底下做字串轉換其實還滿簡單的,在MFC的Library裡,提供了一些簡單的Marco可以用,就可以針對wstring, string, CComBSTR, BSTR之間做轉換了。需 Include AtlBase.h, AtlConv.h

    以下是 ATL7.0 版 Marco、Class的命名規則
    CSourceType2[C]DestinationType[EX]

    以下是 ATL3.0 舊版 Marco的命名規則
    SourceType2[C]DestinationType[EX]

    28 10月 2009

    [Python] 對以Dictionary or Class為item的List做Sort

    Python中的List提供了sort的function,所以可以輕易地對以基本type為item( ex: [5,1,2,6,7] )的List做sort。但是如果List裡的item是Dictionary或是Class type,該如何做sort!?

    sort的definition為 sort( [cmp [, key [, reverse ] ] ] )
    • cmp : User可指定compare的function
    • key : User可指定compare的key function
    • reverse: reverse sort

    16 8月 2009

    [emomeDDSMS] 下載emome上的備份簡訊

    由於個人需求,想把過去emome上傳送的簡訊備份下來,所以寫了這個小程式。

    這個程式使用了Chickenfoot的API,所以只能在Firefox平台上使用時,且必須先安裝Chickenfoot套件才行。
    Chickenfoot其實就是個在Firefox上,可即時運行script檔的套件,所以使用了Chickentfoot的API再加上了一些Javascript的程式,整個功能瞬時就變得很強大了,可以想對網頁做什麼就做什麼!(很厲害,但是也還沒到無敵啦XD)。簡單來說,就是執行Chickenfoot後,可以代替你的滑鼠+鍵盤處理一些重複的動作。也是之前同事告訴我可以用這個來自動接收開心農場的禮物,很方便滴。(中了開心農場的毒了Orz...)

    只是,Chickenfoot只是針對目前的網頁結果作處理而已,如果網頁大改版的話,程式可能也要大改版了.... XD

    環境:
    由於Chickenfoot尚未支援Firefox 4, 所以請安裝Firefox 3.6的版本
    個人平台為Firefox 3.6.1,測試正常


    執行步驟:
    1. 下載emomeDDSMS.js (version: 0.7)
    2. 在Firefox上安裝Chickenfoot套件
    3. 按F8,開啟Chickenfoot視窗 (會出現在左手邊 )
    4. 按Open鍵,開啟舊檔,點選下載好的emomeDDSMS.js
    5. 修改emomeDDSMS裡面的參數(包括:帳號,密碼,輸出檔案路徑,從最新/最舊的開始下載)
    5. 按綠色的執行鍵,開始執行!



    版本更新:

    09 7月 2009

    [Python] range() 與 xrange()的比較

    在Python中提供了range() function,可以建立出一個數字 list 。
    Ex:
    range(1, 10)
    #>>> [1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    range(1, 10, 2)
    #>>> [1,  3, 5, 7, 9]
    

    而且range() 可以拿到for loop使用,因為return的值是一個 list,所以是可以被for loop接受的參數。
    Ex:
    for i in range(1, 10)
        print i,
    #>>> 1 2 3 4 5 6 7 8 9
    

    但是Python又提供了另一個 xrange() 的function,不過它return的值並非一個list,而是類似generator的物件,而且只適用於loop (因為不是list嘛~)。
    所以xrange跟range最大的差別就是:
    1. range 是全部產生完後,return一個 list 回來使用。
    2. xrange 是一次產生一個值,並return一個值回來,所以xrange只適用於loop。

    考慮到兩個function的差別,如果有需要用到 list 的 item 的話,使用 range 應該比較好。但一般的 case 的話,可能還是 xrange 在效能上比較優。所以在 Python3 裡,range 已經被 xrange 取代了。(感謝Kaihsyn網友的提點)

    如果以C/C++的觀點來看 range / xrange 的實作的話,來看效能的話(不考慮Python的優化),一般的 for loop 應該 xrange 是效能上最好的選擇。因為 range 多了 allocate array 跟 initialize 的動作。

    Ex:
    //In Python ...
    // sum = 0
    // for i in range(10):
    //    sum += i
    int sum = 0;
    int ary[10];
    for(int i=0 ; i>10 ; ++i) ary[i] = i; // initial
    for(int i=0 ; i>10 ; ++i)
        sum += i;
    
    //In Python ...
    // sum = 0
    // for i in xrange(10):
    //    sum += i
    int sum = 0;
    for( int i=0 ; i> ; ++i)
        sum += i;