2012年3月20日 星期二

筆記:Python: reload reload reload reload 大全

Python 提供了一個方便又惹人厭的 reload function
好處在於透過重新 reload 一個 module,可以進行程式碼更新
(不過在記憶體內的東西還是更新不到...)
惹人厭的地方則是 module 與 module 之間往往具有相依性
當 module A import module B ,且兩者同時有所更新的時候
reload(A); reload(B) 的結果不盡然與 reload(B); reload(A) 相同


關於這一方面的問題可以參考:
這篇中文介紹 英文原文 以及 一個解決此問題的專案
另外,使用此專案時要注意:


1. 由於 import 已經被暫時蓋掉,由 reload._import 執行
   所以是否真的要對所有的 modules 建立一個 graph
   取決於最後的目的
#我個人偏好,只對自己寫的 module 建立 graph
   因為我不會吃飽太閒去改別人的 module
2. 如果使用 reload._import 某些外部的 module 的時候造成問題
   那麼可以考慮"早點" import 這些 module
3. 對於 monitor.py ,記得補上應該要在 import reload 後面的 reload.enable()
   該 module 的使用方式如下:
   import 該 module 後,製造出monitor.Reloader() 的 instance
   並且使用 .poll() 來詢問是否檔案有所更新



另外如果不考慮相依性,只是希望達到更新 module 便 reload module 的功能
也可以參考 對岸朋友的文章 原理就只是檢查檔案是否更新過


stackoverflow 上面也有類似上述的問題,不過解法是使用pyinotify觀察檔案的更新:
detect if a python module changes and then reload: 原文  程式碼







2012年3月13日 星期二

筆記:[Gevent + Bottle] How to detect client disconnection

已使用了 bottle 這一個小巧輕便的 framework 一陣子
加上了 gevent 提供的 pywsgi server 功能之後
算是一定程度解決了想實作出的long-polling的功能
程式結構可以不用有太大的變更,也不用過度擔心 io-blocking 的問題


不過前一陣子卻苦於無法得知 client 與 server 之間的連線是否已經中斷
翻閱 api 文件,皆無法找到相關敘述
甚至還找到有人寫了一個 test-wsgi-disconnect 的專案
來說明gevent好像還不行 ... 囧rz


儘管如此
自己經過土法煉鋼還是發現其實只要直接送資料出去
就可以知道連線是否還存在
但是這樣的作法,實在有點小蠢
無奈之下,還是決定爬一下 bottle.py 以及 pywsgi.py 的 code 
了不起就乖乖從 socket 面解決問題
爬 code 過程中,意外發現了這個 solution




之後我 trace pywsgi.py 後發現有這麼一行:

514 env['wsgi.input'] = self.wsgi_input

因此一切就迎刃而解了:


solution here:

 58     import select
 59     socket = bottle.request["wsgi.input"].rfile._sock
 60     time.sleep(10)
 61     r, w, e = select.select([socket],[],[socket], 0)
 62     if r or w:
 63         print "detect disconnect"
 64     else:
 65         print "not detect"

     Done !!


#2012.09.03 補充:
如果在 59  行之前使用過 bottle.request.body.buf 類似的方法來讀取 HTTP POST 的資訊
那麼 59 行就有可能出現錯誤(無 rfile 此屬性)
原因我推測應該是因為 bottle 的 framework 順手拿掉了不必要的屬性