概説 Tornade – ロングポーリング


20160130_tronade_long_polling

概説 Tornade の ロングポーリング の記載が、そのままでは動かなかった。

下記のエラーが発生します。

AttributeError: 'StatusHandler' object has no attribute 'async_callback'

Tornado 1.0 では、async_callback は、コールバックで発生した例外をキャッチするために、明示的に指定する必要がありましたが。
Tornado 4.3 では、不要になり、メソッド自体が削除されたようです。

下記のように修正します。

class StatusHandler(tornado.web.RequestHandler):
	@tornado.web.asynchronous
	def get(self):
#		self.application.shoppingCart.register(self.async_callback(self.on_message))
		self.application.shoppingCart.register(self.on_message)

概説 Tornade – 非同期Webサービス


20160126tornade_async

概説 Tornade の 5章 非同期Webサービス の記載が、そのままでは動かなかった。

サンプルとして、Twitter API を使っているが。
ずいぶん前に、変更になって、OAuth 認証を必要になった。

http://search.twitter.com/search.json

OAuth 認証を通すというやり方をあるが、そこは本質ではないので、
Twitter API もどきを作ってみた。

fake_twitter_server.py

from bottle import HTTPResponse, route, run
from datetime import datetime, timedelta
import time

@route('/')
def home():
    now = datetime.now()
    tweets = []
    for n in range(1,100) :
        t = now - timedelta(hours=+9, milliseconds=100*n)
        c = datetime.strftime(t, "%a, %d %b %Y %H:%M:%S +0000")
        tweets.append( '{"created_at":"' + c + '"}' )
    body = '{"results": [' + "\n"
    body += ", \n".join(tweets) + "\n"
    body += ']}'
    r = HTTPResponse(status=200, body=body)
    r.set_header('Content-Type', 'application/json')
    time.sleep(0.05)
    return r

run(host='0.0.0.0', port='9999')

これをどこかのサーバーで動作させる。
ローカルネット内だと、応答が速すぎて、同期と非同期の違いが出なかった。

Tornade 側
tweet_rate.py

#		response = client.fetch("http://search.twitter.com/search.json?" + \
#				urllib.urlencode({"q": query.encode('utf8'), "result_type": "recent", "rpp": 100}))
		response = client.fetch("http://YOUR_IP:9999") 

Sierge によるレンポンスの違い
同期:10.02 trans/sec
非同期:14.37 trans/sec
ジェネレータ: 14.59 trans/sec


Python Bottle


20160126bottle_site

Bottle は Python 用の軽量のWEBフレームワークです。

インストール

$ pip install bottle

サンプルコード

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)

WEBブラウザで

http://localhost:8080/hello/world

20160127bottle


Siege


20160126siege

Siege は、HTTP のロードテストやベンチマークのユーティリティです。
ちなみに、Siege とは、城などを包囲して攻撃することです。

インストール

$ brew install siege
...
/usr/local/Cellar/siege/3.1.3: 18 files, 249.6K

使い方

$ siege http://localhost/ -c10 -t10s

結果の例

Transactions:		          92 hits
Availability:		      100.00 %
Elapsed time:		        9.18 secs
Data transferred:	        0.02 MB
Response time:		        0.40 secs
Transaction rate:	       10.02 trans/sec
Throughput:		        0.00 MB/sec
Concurrency:		        4.05
Successful transactions:          92
Failed transactions:	           0
Longest transaction:	        0.75
Shortest transaction:	        0.09

参考
WEBサイト負荷テストツール7選


概説 Tornade – データベース


20160125toronade_database

概説 Tornade の 4章 データベース の記載が、そのままでは動かなかった。

MongoDB との接続
pymongo-3.2 では、Connection ではなく、MongoClient を使います。

pymongo.Connection()

          ⬇️

pymongo.MongoClient()

レコードの挿入
これは誤記ですね。4章全体に見られます。
ぱっと見は分かりにくいですが、) と } が逆です。

widgets.insert({"foo": "bar")}

          ⬇️

widgets.insert({"foo": "bar"})

おまけ
138ページの記載をスクリプトにしたもの
books.py

import pymongo

conn = pymongo.MongoClient()
db = conn["bookstore"]

db.books.insert({
    "title":"Programming Collective Intelligence",
    "subtitle": "Building Smart Web 2.0 Applications",
    "image":"/static/images/collective_intelligence.gif",
    "author": "Toby Segaran",
    "date_added":1310248056,
    "date_released": "August 2007",
    "isbn":"978-0-596-52932-1",
    "description":"<p>This fascinating book demonstrates how you can build web applications to mine the enormous amount of data created by people on the Internet. With the sophisticated algorithms in this book, you can write smart programs to access interesting datasets from other web sites, collect data from users of your own applications, and analyze and understand the data once you've found it.</p>"
})

db.books.insert({
    "title":"RESTful Web Services",
    "subtitle": "Web services for the real world",
    "image":"/static/images/restful_web_services.gif",
    "author": "Leonard Richardson, Sam Ruby",
    "date_added":1311148056,
    "date_released": "May 2007",
    "isbn":"978-0-596-52926-0",
    "description":"<p>You've built web sites that can be used by humans. But can you also build web sites that are usable by machines? That's where the future lies, and that's what this book shows you how to do. Today's web service technologies have lost sight of the simplicity that made the Web successful. This book explains how to put the &quot;Web&quot; back into web services with REST, the architectural style that drives the Web.</p>"
})

cursor = db.books.find()
for document in cursor:
    print(document)


MongoDB for Python


MongoDB は、NoSQL 型のデータベースです。

Python ドライバーのインストール

$ pip install pymongo

CRUD操作
下記にサンプルが掲載されています。
Getting Started with MongoDB (Python Edition)

Python のサンプルコード

from pymongo import MongoClient
from datetime import datetime

client = MongoClient()
db = client.test
result = db.restaurants.insert_one(
    {
        "address": {
            "street": "2 Avenue",
            "zipcode": "10075",
            "building": "1480",
            "coord": [-73.9557413, 40.7720266]
        },
        "borough": "Manhattan",
        "cuisine": "Italian",
        "grades": [
            {
                "date": datetime.strptime("2014-10-01", "%Y-%m-%d"),
                "grade": "A",
                "score": 11
            },
            {
                "date": datetime.strptime("2014-01-16", "%Y-%m-%d"),
                "grade": "B",
                "score": 17
            }
        ],
        "name": "Vella",
        "restaurant_id": "41704620"
    }
)
cursor = db.restaurants.find()
for document in cursor:
    print(document)

実行する

$ python /Users/ohwada/Desktop/mongo.py

{u'cuisine': u'Italian', u'borough': u'Manhattan', u'name': u'Vella', 
u'restaurant_id': u'41704620', u'grades': [{u'date': datetime.datetime(2014, 10, 1, 0, 0),
u'grade': u'A', u'score': 11}, {u'date': datetime.datetime(2014, 1, 16, 0, 0), u'grade': u'B',
u'score': 17}], u'address': {u'building': u'1480', u'street': u'2 Avenue', u'zipcode': u'10075',
u'coord': [-73.9557413, 40.7720266]}, u'_id': ObjectId('56af99d453b872846eb24c3a')}

以下、省略


MongoDB


20160124mongodb

MongoDB は、NoSQL 型のデータベースです。
BSON と呼ばれる JSONのバイナリ版でデータを保存します。

インストール

$ brew install mongodb

起動

$ mongod --config /usr/local/etc/mongod.conf &

バージョン確認

$ mongo -version
MongoDB shell version: 3.0.7

CRUD操作
下記にサンプルが掲載されています。
Getting Started with MongoDB (MongoDB Shell Edition)

対話型シェルを開始する

$ mongo

データの Create

use test

db.restaurants.insert(
   {
      "address" : {
         "street" : "2 Avenue",
         "zipcode" : "10075",
         "building" : "1480",
         "coord" : [ -73.9557413, 40.7720266 ],
      },
      "borough" : "Manhattan",
      "cuisine" : "Italian",
      "grades" : [
         {
            "date" : ISODate("2014-10-01T00:00:00Z"),
            "grade" : "A",
            "score" : 11
         },
         {
            "date" : ISODate("2014-01-16T00:00:00Z"),
            "grade" : "B",
            "score" : 17
         }
      ],
      "name" : "Vella",
      "restaurant_id" : "41704620"
   }
)

WriteResult({ "nInserted" : 1 })

データの Read

db.restaurants.find()

{ "_id" : ObjectId("56af84dea36250ac8cfad145"), "address" : { "street" : "2 Avenue", "zipcode" : "10075", "building" : "1480", "coord" : [ -73.9557413, 40.7720266 ] }, "borough" : "Manhattan", "cuisine" : "Italian", "grades" : [ { "date" : ISODate("2014-10-01T00:00:00Z"), "grade" : "A", "score" : 11 }, { "date" : ISODate("2014-01-16T00:00:00Z"), "grade" : "B", "score" : 17 } ], "name" : "Vella", "restaurant_id" : "41704620" }

以下、省略


Python Tornado


Tornado は Python で書かれたWebフレームワークです。

インストール

$ pip install tornado

サンプルコード

import tornado.ioloop
import tornado.web

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")

def make_app():
    return tornado.web.Application([
        (r"/", MainHandler),
    ])

if __name__ == "__main__":
    app = make_app()
    app.listen(8888)
    tornado.ioloop.IOLoop.current().start()

実行

$ python hello.py

スクリーンショット
20160122_tronade_hello

参考
Tornado (Webサーバ) – wikipedia
日本語ドキュメント
英語ドキュメント


ラズパイに FTDI ドライバーをインストールする


ラズパイに FTDI ドライバーをインストールします。
FTDI は FTDI 社の USB シリアルのチップです。
多くの装置で採用されています。

FTDI のサイト では、FTDI ドライバーの一覧が用意されています。
FTDI ドライバーは、Windows、MAC、Linux などのOS毎に用意されています。
Linux では、x86、ARM、MIPS などのCPU毎に用意されています。
20160120ftdi

さらに、ARM用には、下記の4種類が用意されています。
(3) が Raspberry Pi 用となっていますが、これは最初の製品群の ARM11コア用です。
Raspberry Pi 2 は ARM7コアなので、(4) を使用します。

(1) ARMv5 soft-float
(2) ARMv5 soft-float uClibc
(3) ARMv6 hard-float (suits Raspberry Pi)
(4) ARMv7 hard-float

1. インストール

$ sudo su -
# cd /tmp
(ファイルのダウンロード)
# wget http://www.ftdichip.com/Drivers/D2XX/Linux/libftd2xx-arm-v7-hf-xxx.tgz
(ファイルの解凍)
# tar xfvz libftd2xx-arm-v7-hf-xxx.tgz
(ファイルのコピー)
# cp release/build/libftd2xx.* /usr/local/lib
# chmod 0755 /usr/local/lib/libftd2xx.so.1.3.6
# ln -sf /usr/local/lib/libftd2xx.so.1.3.6 /usr/local/lib/libftd2xx.so
# exit

2. ビルドのテスト
正しくビルドできるかテストします。
(1) ビルド

$ cd /tmp/release/examples
$ make -B
$ cd EEPROM/read

(2) ラズパイのUSBポートに FTDI モジュール を接続します。

(3) OSがドライバーモジュールを登録している場合は、いったん削除します。

$ sudo lsmod
(ftdi_sio や usbserial があれば、下記のコマンドで削除する)
$ sudo rmmod ftdi_sio
$ sudo rmmod usbserial

(4) プログラムを実行する。
下記のような表示が出れば、OKです。

$ sudo ./read
Library version = 0x10306
Opening port 0
FT_Open succeeded.  Handle is 0x17e52c8
FT_GetDeviceInfo succeeded.  Device is type 5.
FT_EE_Read succeeded.

Signature1 = 0
Signature2 = -1
Version = 2
VendorId = 0x0403
ProductId = 0x6001
Manufacturer = FTDI
ManufacturerId = A9
Description = FT232R USB UART
SerialNumber = A9009fw9
MaxPower = 90
PnP = 1
SelfPowered = 0
RemoteWakeup = 1
(省略)

3. デバイスの確認
FTDI モジュールがUSBシリアルと認識さているかを確認します。
いったん、リブートします。
ls コマンドで、FTDI モジュールを接続する前と、後の変化を見ます。
下記のように ttyUSB0 として認識されていれば、OKです。

$ ls /dev/tty*
/dev/ttyUSB0

4. 動作確認
下記のコマンドで、相手装置に文字列を送信します。

(ボーレートの設定)
$ stty -F /dev/ttyUSB0 9600
(文字列の送信)
$ echo hello > /dev/ttyUSB0

相手装置が受信できれば、OKです。

参考
Raspberry PiでFTDIデバイスドライバをインストールする