2015年12月15日 星期二

[RPI]rpi-raspbian-設定網路

最近改用 raspbian,也就是 raspberry pi 的 debian 版本。
開機之後,發現不會設定無線網路,終於找到一個自己很熟悉的方法。

需要幾個指令:

ifconfig -- 用來開啟/關閉介面卡
iwconfig -- 用設定無線的 SSID, key
iwlist -- 用來搜尋周圍 AP
dhcpcd -- 經由 dhcp 得到 ip

首先,先找出你的無線網卡是哪個名字
ifconfig -a

找到介面的名字後,若是沒有打開,就把它打開
ifconfig wlan0 up

接著,設定無線網卡的 SSID (在 linux 世界都叫它 ESSID)
iwconfig wlan0 essid <essid>

還有設定無線網卡的金鑰
iwconfig wlan0 key <key>

最後,設定 ip,若是使用 dhcp,使用指令如下
dhcpcd wlan0

指定 ip 則是使用下例指令
ifconfig wlan0 192.168.1.2
網路匣道設定
route add default gw 192.168.1.1

我以前就會,現在真的忘光光了。
http://betaparticle.pixnet.net/blog/post/41609278

2015年12月6日 星期日

[超譯]bottle 非同步應用入門

#非同步應用入門

非同步的設計模式沒有辦法與 WSGI 的同步本性好好的融合。
這也就是為何多數非同步的架構(framework, ex:tornado, twisted)實作特殊的 API 才能使用他們的非同步特性。
Bottle 是一種 WSGI 架構,也就有 WSGI 的同步本性,所幸有超讚的 「gevent 專案」,bottle 仍有可能寫出非同步應用。
本文就在說明擁有非同步 WSGI 的 bottle 的使用。

#同步 WSGI 的限制
簡單來說,WSGI 規範(pep 3333) 定義一個 request/response 的循環,如後:
對於每個 request,應用程式可呼叫點被呼叫一次,就要「必須」回傳一個內容列舉。
有了那個列舉,server 就會用它來逐步取得內容,然後一次一次寫到 chunk 進 socket。
當該列舉到盡頭,client 連結就被關掉。

足夠簡單,但有個小問題,這就是所謂的同步呼叫。如果你的應用需要等待一些資料(IO, sockets, databases,...),這就只有兩個選擇,要嘛先 yeild 一個空字串(empty string),再不就卡住當前的執行緒(thread)。以上兩選擇,都將佔住處理的執行緒,造成無法回應新的 request。這就造成一個執行緒同一時間只能處理一個 request。

多數 server 會限制執行緒數目避免太多的負荷,一個執行緒池(pools)大多是設定執行緒數目在 20 以下。只要所有的執行緒都有事做,任何新的連線都會卡住。此時對其他人而言跟死掉沒兩樣。如果,你打算實作一個聊天室,採用 long-polling ajax request 以取得即時的更新,你很容易就碰到 20 個同時連線的限制。這只是個非常小的聊天室而已。

#救援投手上場 greenlet
多數 server 限制 worker pools 擁有的執行緒數目在一個相對低檔的數字,是因為執行緒切換與產生新執行緒的代價頗高。與fork 行程(process)相比,執行緒比較便宜沒錯,但為每個連線建一個新的執行緒還是滿貴的。

gevent 模組加入 greenlet 這個東西。Greenlet 與傳統的執行緒行為一樣,但建立 greenlet 很便宜。一個採用 gevent 的 server,可以產生出數千個 greenlet,一對一處理每個連線,而且幾乎沒有額外代價。任何一個 greenlet 卡住,不會影響 server 接受新 request 的能力。可同時間處理的連結數幾乎是無限制。

這讓建立一個非同步應用不可思議的簡單,因為他看起來就跟同步的應用一樣。一個 gevent 的 server,實際上不是非同步,它行為像是超多執行緒。以下是範例:

    from gevent import monkey; monkey.patch_all()
   
    from time import sleep
    from bottle import route, run
   
    @route('/stream')
    def stream():
        yield 'START'
        sleep(3)
        yield 'MIDDLE'
        sleep(5)
        yield 'END'
   
    run(host='0.0.0.0', port=8080, server='gevent')

第一行,超重要。它讓 gevent 把 python 多數的阻塞式 API 變成不會阻塞現用執行緒,而是讓 CPU 去處理下一個 greenlet。它實際上是用 gevent 的 pseudo-thread 取代 python 的 threading 模組。因此,你仍可以用 time.sleep() 來卡住整個執行緒。如果你對於取代 python 內建模組不舒服,那可以使用對應的 gevent 函式(在此範例是 gevent.sleep())

如果,你執行這個腳本,然後用瀏覽器指到 http://localhost:8080/stream,你應該可以看到 START, MIDDLE, END 一個接一個的出現(而不是等 8 秒後一次看見它們)。這行為與使用一般執行緒是一樣的,但是你的 server 可以同時處理數千個 request 也不會有問題。

    note: 有些瀏覽器會暫存一些資料再開始畫頁面。這情況發生時可以 yield 多點資料看看是否有改善。另外,多數瀏覽器自身就會有限制一個 URL 只開一個連線。若是遇到這問題,你可使用第二個瀏覽器或是效能評估工具(例如 ab 或 httperf)來量測效能。
   
#事件 callback
非同步架構中(包含 tornado, twisted, node.js),一種常見的設計模式是使用非阻塞 API,綁一個 callback 到非同步事件。像是 sccket 物件是持續開啟,直到明確被關閉,也允許稍後有資料時呼叫 callback 寫入到 socket。這裡有個 tornado library 的範例:

    class MainHandler(tornado.web.RequestHandler):
        @tornado.web.asynchronous
        def get(self):
            worker = SomeAsyncWorker()
            worker.on_data(lambda chunk: self.write(chunk))
            worker.on_finish(lambda: self.finish())
   
主要的好處是,request 的 handler 可早點被結束掉。該執行緒就有空可處理新 request,當 callback 被呼叫時依然能把前一個 request 的資料寫到 socket 去。這些架構就能以小量作業系統的執行緒同時處理許大量 request。

使用 gevent + WSGI 的時候,事情就不是這樣了。首先,提早結束這件事沒有益處,因為我們擁有無限制的(pseudo)執行緒池可以接收新的 request。第二,我們也不能提早結束,因為這會讓 socket 被關掉(這是被 WSGI 要求的)。第三,我們必須回傳一個列舉以符合 WSGI。

為了要符合 WSGI 標準,我們能做的,就是回傳內容的列舉,而該列舉是可以非同步的寫入。有了 gevent.queue 的幫助,我們能「模擬」一個斷開的 socket,然後把前面的範例改寫如下:

    @route('/fetch')
    def fetch():
        body = gevent.queue.Queue()
        worker = SomeAsyncWorker()
        worker.on_data(body.put)
        worker.on_finish(lambda: body.put(StopIteration))
        worker.start()
        return body
   
從 server 的角度來看,這個 queue 物件是可列舉的。它會阻塞住,如果它沒有內容,而當他遇到 StopIteration 的時候會馬上停止。這符合 WSGI。在應用程式這邊,queue 物件表現就跟個非阻塞的 socket 一樣。你可以在任何時候寫入它,傳遞它,甚至開一個 pseudo 執行緒以非同步方式寫入它。這就是多數 long-polling 的實作方法。

#最後一招 websocket
讓我們暫時忘記底層的細節,來談談 WebSocket。既然你在讀這文章,或許你知道 websocket 是什麼。它是一個雙向溝通的通道,存在於瀏覽器(client)與網路應用程式(server)之間。感謝 gevent-websocket 套件,已經把難的工作都做完了。這裡有個簡單的 websocket 端點,它可以接受訊息然後傳回去給 client:

    from bottle import request, Bottle, abort
    app = Bottle()
   
    @app.route('/websocket')
    def handle_websocket():
        wsock = request.environ.get('wsgi.websocket')
        if not wsock:
            abort(400, 'Expected WebSocket request.')
   
        while True:
            try:
                message = wsock.receive()
                wsock.send("Your message was: %r" % message)
            except WebSocketError:
                break
   
    from gevent.pywsgi import WSGIServer
    from geventwebsocket import WebSocketError
    from geventwebsocket.handler import WebSocketHandler
    server = WSGIServer(("0.0.0.0", 8080), app,
                        handler_class=WebSocketHandler)
    server.serve_forever()

while-loop 一直執行到 client 關掉連線。你知道的 :)

client 端的 javascript API 也很直接:
    <!DOCTYPE html>
    <html>
    <head>
      <script type="text/javascript">
        var ws = new WebSocket("ws://example.com:8080/websocket");
        ws.onopen = function() {
            ws.send("Hello, world");
        };
        ws.onmessage = function (evt) {
            alert(evt.data);
        };
      </script>
    </head>
    </html>
   
   
原文:
http://bottlepy.org/docs/dev/async.html

2015年11月29日 星期日

[讀書心得]改變世界的九大演算法

«改變世界的九大演算法»裡面,九大演算法其實是講九大類的演算法。也可以說是九個應用方面的演算法。作者在每一類演算法會試著講解一個到數個演算法的名字,然後挑一個容易用文字說明的演算法,仔細描述它是如何發生作用的,並說明它所帶來的影響。

當然作者的九個應用方面也不是隨便挑的,還是符合現代社會的主題「網路」、「連結」,由這兩個主題所要解決的問題有:網頁搜尋、網頁排名、 資料傳輸、資料儲存、資料分類(人工智慧)。於是,這些問題的解決方法,就很自然地展開為第二章到第九章。對,第二章到第九章。腦筋有在轉的朋友應該會算一下,從二數到九,只有八個。那第九個到哪兒去了?

我看完之後,也找了一下,到底是我有問題還是作者有問題?於是我翻來翻去,終於在封底找到了一句可證明第十章說的就是那個第九個演算法。那個「如果存在的話,將會很了不起的偉大演算法」,就放在第十章落落長的數學反證法的描述裡,非常值得一生細讀一次。第十章裡面還有哲學性的思考,人類的創造物,電腦,是否會因為人腦的極限而有極限?

過往的世界,很多光芒都從電腦這個學科裡爆發,作者也在第十一章說明一個淺顯的道理,因為電腦是前所未有的新領域,隨手撿來都是寶石。跟前期的物理爆發、更前期的化學爆發一樣。然而,接下來的時代,進入穩定成長期的演算法研究,想發現新的偉大演算法,就像在滿是繁星的夜空中,想要發現一顆沒被發現又耀眼奪目的星星。

我覺得最重要的是第十一章,建議大家從第十一章開始讀再回頭讀第一章。想要了解演算法不用知道任何電腦語言。書裡所說的演算法都是概念,語言是一個表達概念的工具,所以用任何語言都可以表達。重要的是知道,我們既習以為常、以為萬能的電腦,它能做什麼,又不能做什麼。才不會自尋煩惱。

2015年11月25日 星期三

[python]微型 web 框架對戰 flask vs bottlepy

這個是舊文了,只是我把以前的文章拿來重新整理以符合時代。
有些東西是恆久不變有價值的,就留下來,有些則可與時俱進,有些該丟的也要丟一丟。


舊文連結:https://www.dotblogs.com.tw/rickyteng/2014/01/19/141704
------
flask 是另一個微型的 web 框架,最近也開始比較為人所知。他的開發者是 Armin Ronacher,同時也是 Werkzeug 及 Jinja2 的開發者。

在 stackoverflow 上有人問了,這兩個微型框架各有所長,為何不合在一起做瀨尿牛丸? 為何不合併成一個完美的框架呢?

(以下為超譯)

Ronacher 先生回應說:「我有試過,但是 flask 是有相依於 Werkzeug 及 Jinja2,而 bottle 的開發者很堅持只要一個檔案,他對於合併後會變成很多檔案這事不開心。」

結果底下 bottle 的開發者之一 defnull 就電說:「不管是不是一個檔案,bottle 支援 python3,flask 辦不到!」

flask 的擁護者就來說:「那是使用 2to3 功能!不乾淨!」bottle 的擁護者說:「那是以前!現在不是!」

這個爭論一下就結束了。

而下個爭論就在一個檔案上,bottle 的擁護者說:「bottle 的一個檔案,就是比較容易變成其他程式的模組,deploy 也簡單,不用考慮系統相依性!」flask 的擁護者立刻上前:「系統相依性用 virtualenv 就解決啦!」bottle 的擁護者說:「就是比較麻煩啦!還要花硬碟!」flask 擁護者說:「硬碟是幾塊錢啊!」

Dexter 在混戰中衝上前說:「我不是 bottle 的粉絲!我發現 flask 也不錯!可以從零開始要什麼有什麼。

想要 form generation? Flask-WTF.
想要 DB ORM ? Flask-SQLAlchemy.
想要 Authentication system? Flask-login or flask-openid.
想要 migration for DB changes? SQLAlchemy-migrate (old), or Flask-alembic (fairly new still).
想要 AJAX? Try Flask-Sijax
想要 Admin panels? Flask-Admin
想要 to run scheduled executables on system? Flask-celery
想要 email? Flask-Mail」

bottle 擁護者說:「你想要這麼多,用 Django 就好啦!」Dexter 回:「因為 Django 做不好!」( Django 眾:趴著也中槍)

Aaron Meier,也來幫 Dexter 一把:「我要幫 flask 投一票!他的支援度比較好。Dexter 說得對,flask 幾乎有所有你會需要的東西。而且 Armin 是一流的 coder!你不一定要用 Flask-SQLAlchemy,PyORMish 非常棒!我是PyORMish 的作者」(這算是置入式行銷嗎?)

(超譯結束)

此次小混戰就結束了,從各人所言可以多少看到 bottle 與 flask 的特色。好不好用就大家自己開著辦吧!

說真的,如果功能真的要這麼多,web2.py、django、pylon、pyramid、turbogear、zope…等等整套式的框架也很多,真的數不完…。我沒有別的意思,只是 python 的 web framework 真的太多…。



原連結

http://stackoverflow.com/questions/4941145/python-flask-vs-bottle

[python] web 的微型框架 bottle.py

其實這是舊的文章了。只是把我以前的文章再整理一下而已。

舊文連結:https://www.dotblogs.com.tw/rickyteng/2013/12/19/135354
文章中所提的上一次研究 python web framework,該文章是:
http://codebeta.blogspot.tw/2013/11/webpy-webpy-django-web2py.html
cherrypy 後來我就沒有用了,因為我用 GAE 當 local server 撐好久。
------
上一次研究了 python 的 web framework。由於我的應用比較小,所以 web.py 是我比較喜愛的。而最近不小心找到一個小的 framework 叫做 bottle.py,它自稱為 micro framework,微型框架。沒想到,居然更對我的胃口。它有多小呢?它小到只有一個 py 檔 149k,它小到不用安裝,只要有 python,就可以執行!

from bottle import route, run, template

@route('/hello/<name>')
def index(name):
    return template('<b>Hello {{name}}</b>!', name=name)

run(host='localhost', port=8080)

以上是官網上的範例。從範例中可以看到它有內附 template,支援 routing (寫在 decorator 的地方) 以及變數,是很漂亮簡潔的寫法。

不過,它因為太小,以及為了可攜性,所以 http server 是使用 python 內的 WSGIRefServer(),這是只能每次處理一個 request。不過,這不是問題,既然它是使用 wsgi,所以有支援 wsgi 的 server,都可以當做是 bottle.py 的後台。

Server: Built-in HTTP development server and support for paste, fapws3, bjoern, Google App Engine, cherrypy or any other WSGI capable HTTP server.

有人是使用 bottle.py + cherrypy 的組合,我想我接下來會嘗試。但在開發期,或是在家只有5~6台電腦使用的狀況下,我想內建的就很夠用了。

2015年11月22日 星期日

[超譯]Open Sound Control

Open Sound Control 簡稱 OSC,是一個協定,讓電腦,混音器以及其他多媒體裝置之間利用現代網路技術溝通。

把現代網路技術的益處帶進電子樂器的世界裡,OSC 的優勢包含了互動性、準確、彈性以及強化的組織與文件。

這簡單但強大的協定,提供了處理聲音及其他媒體在即時控制時所需要的所有東西,同時保持彈性與易用性。

特色:
開放、動態、URL風格的符號命名規則
符號與高解析數值的參數資料
模式比對語言以指定多個接收者在一個訊息裡
高解析時間標籤
訊息包可同時產生效用
查詢系統動態查詢 OSC 的能力並且找到文件

有很多 OSC 的實作,包括即時聲音與媒體處理環境,網頁互動工具,軟體混音器,多變的程式語言,以及給感測器的硬體裝置。OSC 成功應用的領域有以電腦為基礎的音樂新表達介面、廣域與本地域的網路分散音樂系統,跨執行緒通訊,甚至單一個應用程式。

Highlights:
OSC 規格 http://opensoundcontrol.org/spec-1_0
應用 http://opensoundcontrol.org/osc-application-areas
實作 http://opensoundcontrol.org/implementations
2004 研討會 http://opensoundcontrol.org/2004-osc-conference
CNMAT OSC-kit http://opensoundcontrol.org/osc-kit
OSC 相關出版物 http://opensoundcontrol.org/publications
更多資源 http://opensoundcontrol.org/resources

CNMAT 的 OSC 研究
OSC 原來是在 UC Berkeley Center for New Music and Audio Technology (CNMAT) 的一個研究計畫。CNMAT 是 UC Berkeley 的一個跨學科的研究中心。它以充滿活動的教育,效率,研究計畫而聞名,其專注於音樂與技術創新互動。

原文:
http://opensoundcontrol.org/introduction-osc

2015年11月3日 星期二

2015年9月10日 星期四

[numpy]矩陣操作

我差點把自己搞瘋。關於 dot、inner、outer、cross、* 跟我印象中的不一樣。難怪當初快被當掉…。

反正現在一切以 numpy 說了算…。

首先,平移矩陣的函式先寫出來,方便以後要用。(公式也是抄來的,所謂的齊次座標 homogeneous coordinate) http://openhome.cc/Gossip/ComputerGraphics/HomogeneousCoordinate.htm

def m_shift(vector):
    a = numpy.array([1,0,0,vector[0],
                     0,1,0,vector[1],
                     0,0,1,vector[2],
                     0,0,0,1])
    a.shape = (4,4)
    m = numpy.mat(a.copy())
    return a

 

輸入一個 array 當向量,三個數字依序表示對 x, y, z 做平移的量。

假設就每個軸平移 2 好了,m = m_shift(numpy.array([2,2,2]))

原來的點就假設為 (1,2,3),要給公式用,就取一個 array,v1 = v1 = numpy.array([1,2,3,1])。最後那個 1 是為了齊次座標而補的。

執行 dot 及 * 的結果如下:

m = [[1 0 0 2]
[0 1 0 2]
[0 0 1 2]
[0 0 0 1]]

v1 = [[1]
[2]
[3]
[1]]

numpy.dot(m,v1) = [[3]
[4]
[5]
[1]]

m * v1 = [[1 0 0 2]
[0 2 0 4]
[0 0 3 6]
[0 0 0 1]]

 

就先這樣吧…。

[python] pyinstall 在 windows 上的安裝使用

這次需要把 python 的程式丟到一個沒有裝 python 環境去,所以需要打包它。

預期的目標是不要事先安裝 python。

為了文章閱讀流暢,一些可選的手法就容後再補充了,免得原來是說明文的,變成手冊文。

我的環境是 windows 7, python 2.7, pyinstaller 2.1。

 

首先尋找 pyinstall 這個程式。從 pypi 下載 zip 檔。

https://pypi.python.org/packages/source/P/PyInstaller/PyInstaller-2.1.zip#md5=3eb18a454311707ab7808d881e677329

 

把它解開放到任何你想要的目錄。

然後在那裡開個命令列視窗,執行 setup.py install

安裝完之後,會在 C:\Python27\Scripts 的目錄裡,有 pyinstaller.exe。

然後在那裡開個命令列視窗,執行 pyinstaller --version

看到 2.1 的數字跑出來,就是安裝成功了。

 

在完成安裝之後,在 C:\Python27\Scripts 裡,會同時有以下的執行檔。

  • pyinstaller
  • pyi-makespec
  • pyi-build
  • pyi-archive_viewer
  • pyi-bindepend
  • pyi-grab_version
  • pyi-make_comserver

 

為了方便,請記得將 C:\Python27\Scripts 加到 windows 的執行路徑裡。

image

 

接下來實際做一個例子來試用 pyinstaller。

程式的功能,目前先設計為:

  1. 讀取外部的 json 檔裡的路徑設定
  2. 列出該路徑下的所有的專案檔 (結尾是 vbproj)

 

所以,打開 IDLE,寫 python 程式如下 path_info.py:

import json
import os

path_info_path = 'path_info.json'
path_info = []
def read_info():
    global path_info
    f = open(path_info_path,'r')
    path_info = json.load(f)
    f.close()

vbproj_list = []
def get_vbproj_list():
    global vbproj_list
    for path in path_info:
        for root,dirs,files in os.walk(path):
            for i in files:
                if i.endswith('.vbproj'):
                    vbproj_list.append(os.path.join(root,i))

if __name__ == '__main__':
    read_info()
    get_vbproj_list()
    for i in vbproj_list:
        print i

path_info.json 裡面的內容也準備好。

[
    ".",
    "..\\tmp\\"
]

 

打開命令列,位置換到 path_info.py 的位置

執行 >pyinstaller path_info.py

在一連串的輸出之後,在 dist 裡面會有 path_info 的目錄,裡頭就是執行所需的檔案,會有一個 path_info.exe,因此這一包 zip 起來就可以傳給其他人用。

如果希望是全部打包在一個檔案,就執行 >pyinstaller path_info.py -F

這樣,在 dist 裡面,就會有一個 path_info.exe,這個可以直接給別人用了。

 

 

 

參考:

https://github.com/pyinstaller/pyinstaller/wiki

http://pythonhosted.org/PyInstaller/

http://blog.float.tw/2013/10/use-pyinstaller-packages-python-programs.html

[vmware] 兩步驟把 c 槽硬碟變大 (win xp)

有時候一開始設定的硬碟不夠,會在之後遇到 c 槽不夠大的困境。

這時候,用兩步驟可以把 c 槽變大。

第一步,在 vm (之後叫做 vm1) 關機的情況下,使用 Utility 底下的 Expand 工具長大。

image

image

image

第二步,用另一個 vm (暫且叫做 vm2),把原來的 vm1 的 c 槽掛成 d 槽。開機之後,用 dispart 指令把分割變大。

image

image

image

之後,把 vm2 關機,移除第二顆硬碟。然後再把 vm1 開機,就看到 c 槽變成 20G 了。結束。

2015年5月26日 星期二

[86duino] 86Duino EduCake 101