2012年11月29日 星期四

使用 python Tornado 實作 WebSocket 聊天室

 

早期網頁更新訊息必須 Refresh 整個頁面,這使得網頁互動效果有一定的限制在。後來 AJAX 的火紅,使得網頁的 UX 提升到了另一個境界。

但 AJAX 仍無法有效率的處理 Realtime 的訊息傳遞,最多只能做到 Realtime-like,畢竟仍是 client 主動,server 被動,若 server 有資料更新,client 也只能透過 polling 的方式來偵測資料是否有更新,而這不但 client 辛苦,server 更是得面臨大量的 garbage packet

只要瀏覽器支援,其實透過 WebSocket 來處理是更理想的。WebScoket 跟傳統 socket 在使用上非常相似,都是由 client 主動連線,並在正常情況下可保持連線,使得 server 可直接將訊息送到「連接中」的 client

 

程式碼如下

Server side

chatroom.py

import tornado.ioloop
import tornado.web
from tornado import websocket
 
clients = []
 
class ChatRoom(websocket.WebSocketHandler):
    def open(self):
        clients.append(self)
    
    def on_close(self):
        clients.remove(self)
    
    def on_message(self, message):
        for client in clients:
            client.write_message(message)
 
application = tornado.web.Application([
    (r"/", ChatRoom),
])
 
if __name__ == "__main__":
    application.listen(8000)
    tornado.ioloop.IOLoop.instance().start()

 

Client side

chatroom.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Chat Room</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script language="javascript" type="text/javascript">
$(document).ready(function () {
    var socket = new WebSocket("ws://localhost:8000/");
    socket.onmessage = function(event) {
        $("#message").append("<div>" + event.data + "</div>");
    }
    
    $("#send").click(function() {
        socket.send($("#text").val());
        $("#text").val("").select();
    });
});
</script>
</head>
<body>
<div id="message"></div>
<textarea id="text"></textarea>
<input type="button" id="send" value="send" />
</body>
</html>

 

安裝 Tornado 不多提,實際執行結果如下:

執行 chatroom.py

SNAGHTML2afaaf

 

多開 chatroom.html,就可以進行聊天了

image

2012年10月28日 星期日

網頁快照,把 html 轉換為pdf/image

 

http://cutycapt.sourceforge.net/

 

Ubuntu

sudo apt-get install subversion libqt4-webkit libqt4-dev g++ xvfb
svn co https://cutycapt.svn.sourceforge.net/svnroot/cutycapt
cd cutycapt/CutyCapt
qmake
make
sudo mv ./CutyCapt /usr/local/bin

 

Try it

xvfb-run --server-args="-screen 0, 1024x768x24" CutyCapt --url=http://www.google.com/ --out=example.png

2012年10月27日 星期六

解決 Couldn't resolve host

 

Quick Note:

/etc/resolv.conf 是 DNS 的設定檔,若未設定,可能會導致所有的 domain name 都無法使用。

打開 /etc/resolv.conf 加入底下兩行:

nameserver 8.8.8.8

nameserver 8.8.4.4

2012年10月18日 星期四

javascript dump 複雜型態的物件語法

 

Quick Note:
一般的變數、Array…etc都可以使用這個方法印出深層的資料結構。
有點類似 php 裡面的 print_r
JSON.stringify(obj)

2012年9月4日 星期二

在 Ubuntu 上編譯 PIL

 

Quick Note:
 
假設已經安裝了 pip
 
接著下達以下指令
sudo apt-get install libjpeg8-dev
sudo apt-get install zlib1g-dev
sudo apt-get install libfreetype6-dev
sudo apt-get install liblcms1-dev
sudo ln -s /usr/lib/x86_64-linux-gnu/libfreetype.so /usr/lib/
sudo ln -s /usr/lib/x86_64-linux-gnu/libz.so /usr/lib/
sudo ln -s /usr/lib/x86_64-linux-gnu/libjpeg.so /usr/lib/
sudo ln -s /usr/lib/x86_64-linux-gnu/liblcms.so /usr/lib/

 

如果之前已經安裝了 PIL ,但沒有安裝完整,要先移除

sudo pip uninstall PIL

 

接著安裝 PIL

sudo pip install PIL

2012年8月27日 星期一

區別 Django 中的 STATIC_ROOT 與 STATICFILES_DIRS

 

看此篇文章之前,可以先參考

深入了解 django 的 static 設定

 

本文開始

在寫 django 時,我們會引用許多的 app,也會自行製作許多的 app,每一個 app 都可能有自己的 static 檔案或資料夾。

只要在 INSTALLED_APPS 裡引用的 app,便會成為 python manage.py collectstatic 的收集對象,而收集後存放的路徑,便是 STATIC_ROOT

這麼一來便可以讓 app 有自己的 static 資料夾,不需要混在一起了,維護上也會簡單許多。

django default settings.py 裡面 STATIC_ROOT 的上方,也特別警告我們不應該手動更改 STATIC_ROOT 裡面的檔案。

 

有兩個情況我們需要設置 STATICFILES_DIRS

  1. 專案需要一個 static 檔案或資料夾,但卻不知該如何歸類在哪一個 app 底下。
  2. 專案需要改寫某個引用 app 底下的 static 檔案,但卻不希望動到原本 app 底下的 static 檔案。

狀況一我們有待商榷,畢竟「不知該如何歸類」不應該出現在一個成熟的專案下;而狀況二卻很容易發生。

此時便需要設置 STATICFILES_DIRS,越上方的設置優先權越高,而 STATICFILES_DIRS 的優先權當然也高於 INSTALLED_APPS 內的 app

(INSTALLED_APPS 本身也遵循越上方的 app 優先權越高的原則)

admin 舉例

我若要改寫 django/contrib/admin/static/admin/css/base.css,那麼便可如此指定

STATICFILES_DIRS = (
'/project/mystatic',
)

然後建立 /project/mystatic/admin/css/base.css 檔案後編輯,而後下達

python manage.py collectstatic

 

便會將 /project/mystatic/admin/css/base.css 收集到 STATIC_ROOTadmin/css/base.css 底下,並依照優先權決定覆蓋