顯示具有 python 標籤的文章。 顯示所有文章
顯示具有 python 標籤的文章。 顯示所有文章

2012年9月17日 星期一

用 Sublime Text 2 打造你的 Django IDE



前一段時間我的 MacBook Air 送修,跟某好人借了一台 notebook,灌了 ubuntu 之後環境設定一下一般工作倒是還算順手。不過之前在開發 Django 相關應用的時候我是透過 PyCharm 做為我的 IDE。對於開發 Django 來說,PyCharm 是個很棒的 IDE,有方便的 autocomplete 還有跟 virtualenv 的整合,以及支援 Django template、manage.py 等等的功能,不過功能強大的背後就是很耗費資源,在借來的這台電腦上面跑起來實在是不太讓人開心,所以這次剛好來看一下最近很潮的 Sublime Text 2
關於 Sublime Text 2 的文章 Google 一下可以找到一大堆,這邊我只介紹在開發的時候跟 Django 比較相關的 Package。這些除了自己抓下來之外,還可以透過 Sublime Text 2 的 Package Control 來裝。

Djaneiro

這是我在 Sublime Text 2 上面最喜歡的 Package,它提供了很多 snippet 讓你 coding 的時候可以不用記一堆討厭的名稱。舉例來說,在寫 Django model 的時候常常會有一堆 field 要寫,你可以打入 mchar 再按一下 tab,就會自動幫你產生一個 models.CharField()。試試看這個,你一定會愛上的!

SublimeLinter

無論對於哪個語言來說,有個 Linter 總是會省掉你很多麻煩。這個 Package 支援了許多的 Linter 讓你用。

SublimeRope

Rope 是個很不錯的 Python IDE,在我還在用 emacs 開發 Python 程式的時候 Rope 幫了我不少。SublimeRope 則是把 Rope 當中一些功能移到 Sublime Text 2 上面,讓你作一些 Refactor 等等的動作可以更方便。

Git

最潮的 version control,裝了之後讓你不用切到 command line 就能夠快樂 git

JSFormat

開發 Django 一定多少也會寫一些 JavaScript 的 code,JSFormat 把亂七八糟的 code 變得好看很多。
這些只是一些很基本的 Packages,Sublime Text 2 能作的不僅僅於此,透過 build system 還可以作些跟 unit test 相關的整合。如果你正在找一個順手的 IDE,或許可以試試看用 Sublime Text 2 打造適合自己的開發環境。

2012年8月3日 星期五

python logging 做得好,維護沒煩惱


跟 print 大法說再見


每次在寫程式的時候,我們一定會把程式運行中的訊息記錄下來。在 Python 中,我們很順手地,就會做下面這件事:

    print( "The program meets error %d" % error_code )

比如說,當我們遇到讓我們害怕的bug, 慌張的程師設計師一定會用 print 大法,開始到處印內部的變數。 當你開心地找出問題以後,你一定會很無力地看到不少無用的訊息噴出來....

懶惰的天性使然,一定會等到上線再來整理這些一團亂。

另外,程式中有許多有意義的指標,可以讓我們知道程式運行的狀態,你不會希望它們只是被  print 到螢幕上而已,資訊一定要好好地保存好,甚至是很專業地把log 傳送到 splunk 這種log 分析系統裡,程式才可以被清楚地掌握與管理。

說了這麼多,就是要你除了Business Logic 之外,程式裡面不要有無義意的 print。

請開始用 logging 模組

我們現在就開始用使用python logging 來印出資訊。

首先,用簡單一點的寫法,在你的程式的開頭,可以寫這段code.

import logging

logging.basicConfig(level=logging.DEBUG)

logger = logging.getLogger( __name__ )

這樣就好,沒有別的事情了。

然後,在你的程式中,依照你的需要,你可以寫出如下的 code

logger.debug( "enter the XXX function" )
logger.debug(" user exists 10000 ")

從此以後,你需要做的事就是把資訊,依照 debug, info, warning, error, critical 這些分類來把資訊印出來,像是前面的例子,你只要把第二行的 logging.basicConfig(level=logging.DEBUG) 中的 level 換成別的level: logging.basicConfig(level=logging.INFO)。這樣子的話,程式中為了除錯所加的 debug 訊息就不會再出現了。


不過,上面講的簡略的做法,只是讓你了解logging該怎麼使用,並且只是把 logger.debug 當做可依情況關閉的 print 來用而已,我們需要如下更有彈性的寫法。

這個寫法的原則很重要,請都用下面所說的想法來設計 logging 相關的程式:

  1. 每個 module, class, 都用自已的logger, 當你寫的code, 是一個被人使用的module, 請不要去做多餘的設定。
  2. logger 的名字為了要能方便找出問題,所以不要亂取,通常都是以 module 或是 class 的名稱來命名。
  3. logging 的設定,由整個應用程式的main 函式來決定, 比如說決定該把log 寫到檔案或是將log 傳送到syslogd .我們目前是為了簡單好用才以 logging.basicConfig 當作例子。更實際的例子會用 logging.config.fileConfig. 

所以,當你寫一個 Utility 型式的程式的時候,你只要記好下面這三行code. 其它都不要多想。

import logging
logger = logging.getLogger( __name__ )
logger.debug( "XXX" )


 logging.basicConfig

講完了 Utility 該注意的事情了。你免不了要寫程式進入點。在這裡就是設定logger的地方, 但是python 的logger 由於很有彈性,所以有點複雜。看完了Python logging 的 Reference 以後,我們可要寫像下面落落長的設定才可以把log 寫到 standard error 


恩,要先弄懂 formater, handler。能先弄懂是很好,但若是第一時間弄不懂,你可以把那些設定換成 logging.basicConfig(level=logging.DEBUG) , 就像更前面的例子一樣。若是你想把log 導到檔案中的話,那就只要做一點修改: logging.basicConfig(filename='/tmp/logs', level=logging.DEBUG), 加上 filename 這個 argument就好。 記好 basicConfig 這個捷徑,logging 更快樂~

logging.config.fileConfig

為了更有彈性,更完整的功能,logging module 提供了 ini 檔的格式的設定檔。

有的時候我在想,連logging這件事情都要寫一個config 檔案,就覺得程式設計師好辛苦啊~ 不過苦歸苦,生活還是要過.....

在這裡不講logging 的config 檔怎麼寫,就只講 logging.config.fileConfig 這個function 該怎麼用。

這個function call 做的事還是設定logger, 所以它該出現的地方,跟 logging.basicConfig該出現的地方是一樣的。

不過,在 python 2.6 後,這個 function call 多了一個參數,叫做disable_existing_loggers,使用上,請把它設定成False, 但python 為了向後相容2.5版以前的python,把它的預設值設成了 True. 

如果照它的預設值 disable_existing_loggers=True 來執行的話,在這個function call 之前所get出來的logger,  如果沒有在 config file裡面設定過的話,就會被disable。也就是說,極容易發生你的 module 寫的log 都寫到空氣裡了。

所以,請這樣子用 fileConfig:

    logging.config.fileConfig('log_config_file", disable_existing_loggers=False)

如此,你才有機會看到各個 module 所寫出來的log。

最後

logging 有點複雜,但請熟悉一下這篇文章整理的做法,這樣才能在短時間寫出好維護的好Code!! 當然,還有很多不同的Style 來設定 logger, 如果有不同的Style, 也可以一起討論!

然後,幫強者我同學 Scott 廣告一下他的手機APP (真是不搭) http://blog.walkthisway.tw/post/27802609152/taiwan-host-bnb


2012年6月1日 星期五

Django Sitemap

之前的 SEO 幼幼班 (二)當中,我們提到了登錄 sitemap 的重要性。sitemap 主要是敘述了網站的結構,可以藉由 sitemap 使得搜尋引擎更容易理解網站的內容,藉此幫助搜尋引擎對於網站的索引。這邊我們來告訴大家要如何透過 Django 這個強大的 web framework 來創建動態的 sitemap。

sitemap 怎麼建?

sitemap 是個 xml 檔,格式可以參照 sitemaps.org的描述,基本上來說就是要知道每個 url 的位置、上次更新時間、更新頻率以及權重等等的資料。對於靜態網頁來說,sitemap 可以用人工慢慢的建出來,因為靜態網站不會變動,因此建一次後提交即可。但是對於動態網站或是規模較大的網站來說,可以考慮像是 http://www.xml-sitemaps.com/ 這種 sitemap generator。它會透過 crawler 的方式抓取你的網站,並且建立相對應的 sitemap。

Django sitemap

用手工或是 sitemap generator 的方式生成 sitemap 固然是種方法,但是常常我們的網頁會不斷的新增內容,這個時候用 sitemap generator 定期掃一次的方式可能就不會是那麼即時的更新。對於 Django 這個優秀的 web framework 來說,自動建立 sitemap 當然不會是問題。步驟如下:

在 settings.py 當中加上:

接著就可以訂定 sitemap 當中的成員,假設你今天的網站是個以 blog 為主的網站,那麼你的 views.py 可能會這麼寫:

在這邊我們直接繼承自 Sitemap,設定好 changefreq 根 priority。item 是代表著所有要加入到 sitemap 當中的資料,lastmod 代表著最後更新的日期,location 則是對應到網站的 url。如果你在網站當中有多項資料,那麼只要分別實作不同的 Sitemap 即可。

最後,在 urls.py 當中加入:

這樣就可以完成 sitemap 的創建。

結論

看到 Django 可以那麼輕易的創建出 sitemap 是不是很讓人心動呢?其實 Django 有更多好用的 applications,如果對於 Django 有興趣的人,歡迎參加我們 6/9 以及 6/10 的 PyCon Taiwan,和大家一起了解 Python 以及 Django 的奧妙!

2012年4月27日 星期五

快快樂樂學會 Python decorators

這篇算是改寫自 A primer on Python decorators,不算是翻譯文,因為我懶得照翻 XD 不過例子跟文章結構都是參考這篇文章中擷取出來的。

引子

在 Python 當中,functions 是 first-class objects。也就是說你可以對 function 做任何跟其他 objects 一樣的事情。舉例來說,你可以把一個 function 指定到一個變數當中:

>>> def addone(n):
...     return n + 1
>>> addone(3)
4
>>> add1 = addone
>>> add1(3)
4

這樣看來可能沒什麼,但是當你可以把某個 function 傳入另外一個 function 之後再回傳時,我們可以發現這會有很多有趣的應用。舉例來說,在 Python 裡面有內建 map 這個 function,你只要傳入一個 function 以及一個 list,map 就會回傳一個新的 list,回傳的 list 內容是把你原本傳入的 list 當做輸入,傳進去 function 之後回傳的結果。以下是個例子:

>>> numbers = [1,2,3,4]
>>> map(addone, numbers)
[2, 3, 4, 5]

這樣可以幹啥?

我們透過了 map 這個簡單的例子來示範這麼做的好處,接下來我們來展示一個更棒的例子。

Fibonacci number 的定義如下:

Fibonacci number

Fibonacci seed

如果用 Python 來寫,你可能會寫出下面的 code:

def fib(n):
    if n in [0,1]:
        return n
    else:
        return fib(n-1) + fib(n-2)

這邊我們可以看到,當計算 fib(10) 的時候,會去計算 fib(9) 和 fib(8)。計算 fib(9) 的時候會計算 fib(8) 和 fib(7),這邊我們可以看到 fib(8) 的值被重複計算到了。所以我們希望把重複算過的值記錄下來,這樣就可以省下很多計算的時間,這個技巧叫做 memoization

要達到這個目的,一個簡單的想法是在 fib function 當中用個 dictionary 把算過的值記下來,如果要求的值已經算過了,就回傳存過的值,不過這方法麻煩的地方就是在於還要修改 fib 的程式碼才能達到這個效果。在 Python 當中,我們可以有更好的方法!既然 function 也可以當做回傳值,我們可以把傳入的 function 修改成會把結果記下來的版本再回傳,下面是這個 function 可能的樣子:

def memoize(fn):
    stored = {}

    def memoized(*args):
        try:
            return stored[args]
        except KeyError:
            result = fn(*args)
            stored[args] = result
            return result

    return memoized

這麼一來,我們要產生有 memoization 效果的 fib function 可以這麼做:

fib = memorize(fib)

這跟 decorator 有啥關係?

由於這種 pattern 常常出現,所以 Python 當中提供了 decorators 這個機制來讓你更簡單的做這種事情。

@memoize
def fib(n):
    if n in [0,1]:
        return n
    else:
        return fib(n-1) + fib(n-2)

在這邊,我們會說 memoize 是個 decorator,它 decorate 了 fib 這個 function。其實這邊做的事情跟上面的例子沒有什麼不同,只是透過了 @ 這個 operator 來減少了 coding 的麻煩。

在 decorator 當中,我們也可以傳入參數。舉例來說,如果我們希望用 memcached 來存已經算好的結果,我們可能會寫成下面的樣子:

@memcached('127.0.0.1:11211')
def fib(n):
    if n in [0,1]:
        return n
    else:
        return fib(n-1) + fib(n-2)

這樣寫其實就等同於

fib = memcached('127.0.0.1:11211')(fib)

結論

這邊很簡單了介紹了 Python 當中的 decorator,相信看完之後對 decorator 應該有些初步的了解。Python 當中 decorator 是個很常見的樣式,在各種 framework 當中處處可見。透過 decorator 的應用,將可以讓你的程式碼語義更加的簡潔易懂。

Related Posts Plugin for WordPress, Blogger...