意外なところで嵌るものだ。
Pythonでは乱数生成用のエンジンを何種類か積んでいる。Wichman-Hill(WichmannHillクラス)と、メルセンヌツイスタ(randomクラス)、OSの提供する乱数ジェネレータ(SystemRandomクラス)から選ぶことが出来る。セッションIDに使用するなら、予測不可能でビット数の多い乱数を生成できるSystemRandomクラスを選択したいところなのだが、Google App Engineでは対応していないらしい。セキュリティ上重要なハードウェア乱数が提供されていない辺り、本当に片手落ちだと思う。
デバッガ上だと普通に動くので、気が付くのが遅れた。
・・・と言うわけで、メルセンヌツイスタ(randomクラス)で生成する以外の方法はないようだ。
カテゴリー: Google App Engine
Google App EngineでDjangoメモ
Google App EngineではDjangoというWEBフレームワークを使った開発を行えます・・・そのはずです。とりあえず情報収集中で実現できていないけど、そのメモなどを。
Google App EngineでDjangoを使うには、いくつかの方法があるらしい。
1.Google App Engine Helper for Djangoを使う。
2.Use Django on App Engineを使う。
3.Google App Engine SDK標準のDjangoを使う。
4.標準のDjangoをGoogle App Engineで動かすべく自分で設定する。
3.が理想的な気がするが、標準のGoogle App EngineだとDjangoのver 0.96が起動するらしい。ver1.0やver1.1を動作させるには設定を変更すればよいらしい。でもGoogle App Engineに標準でインストールされているDjangoは古くてセキュリティホール持ちらしい。したがって、DjangoまるごとGoogle App EngineにUpしないと実用には耐えないようだ。→
よって最新のDjangoを落としてきて、1.のGoogle App Engine Helper for Djangoを使うか、Use Django on App Engineのパッチを充てるのがもっとも現実的な解となるようだ。
Google App Engineで日本語を使う
日本語を有効にする
Google App Engineのソースコードに日本語を記述すると、下記のようなエラーが表示されます。Google App Engine Launcherでは正常に動作してしまうので、はまりどころです。
: Non-ASCII character 'x93' in file /base/data/home/apps/mikahosi-1/1.338233447893773564/helloworld.py on line 11, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details (helloworld.py, line 11)
日本語で動作させるためには、下記の一行をソースコードの先頭に記述します。
# -*- coding:utf-8 -*-
UTF-8以外の日本語コードはGoogle App Engine RuntimeとPythonの都合で通らないらしいです。
またPythonで日本語定数文字列を記述するには下記のように先頭にuを追加する必要があります。
text = u"日本語を出力"
Google App EngineをDeployしてみる
Google App EngineにApplicationを作る
最初にGoogle App EngineにApplicationを作成します。Google App Engine LauncherのDashbordボタンをクリックしてGoogle App EngineのWEBサイトを開きます。
Preiewの画面からCreate An Applicationをクリックして新規にアプリケーションを作成します。この時に指定するApplication Identifierは、ApplicationのNameと一致している必要があります。このアプリケーションの例ではmikahosi-1となります。Application Titleも必ず入力しなくてはなりませんが、こちらは任意の文字列で構いません。
Google App EngineにDeployする
Google AccountからApplicationを作成したら、Google App Engine LauncherのDeployボタンをクリックします。下図のログオン画面が表示されますので、ログオンアカウントパスワードを入力してログインします。ここで項目名がmailとなっていますが、指定するのはメールアドレスではありません。Googleのアカウント名(Google Mailと@より前の部分)を入力します。メールアドレスを指定するとログインできません。
初めて使用する場合には、CAPTCHA認証を要求される場合があります。その場合にはDeployment To Googleのコンソール表示にURLを表示します。ブラウザで指定されたURLに接続して、CAPTCHA認証を行ってください。
以上で無事にGoogle App Engineに作成したアプリケーションをアップロードできたはずです。Google App EngineのWEBサイトにて割り当てられたURLに接続してみてください。
ちなみに作成した掲示板サンプルは下記のURLにアップロードしてあります。
http://mikahosi-1.appspot.com/
DataStoreを使ってみる
オブジェクト指向データベース(ODBMS)
クラウド独特のデータストアを使う前に、オブジェクト指向データベース(ODBMS)について知っていると入りやすい。
ODBMSは1980年代後半から、1990年代前半にかけて、様々なオブジェクト指向開発の試行錯誤と研究の中で生まれ、そして殆ど実用される事無く消えつつあった技術です。要は「オブジェクト指向分析の中で表現したデータクラスを、データクラスのままストレージに格納して扱えば、オブジェクトをそのまま表現できて扱いやすいんじゃね?」という発想でした。それまでのストレージはRDBMSに代表される表形式の物で、そこにデータクラスを格納するには非効率な変換処理(ORマッピング)が必要だったのです。
でもODBMSという試みはあまり上手くいきませんでした。ODBMSはリソースを大量に消費するとか、検索が遅いと言った、実装上の問題を抱えている事が多かったのです。その試みはORDBMSやORマッピングやLINQなどとして現在も続いています。そしてクラウドもODBMSを実現するための一つの答えになるものと私は思っています。
初期のODBMSで問題となっていたリソースの消費は、クラウドが安価なリソースを提供することで解決されました。RDBMSとは全く異なるパラダイムの上に成り立っているので、当初は混乱するかもしれません。ですがODBMSはオブジェクト指向開発の効率を大きく高め得るものです。積極的に取り組んでいく価値は高いと思っています。
DataStoreの定義
データの定義は簡単です。以下のようなクラスを定義するだけです。”text”、”date”がメンバ変数です。この二つの値がDataStoreに保存されます。
class GuestComment(db.Model): text = db.StringProperty(required=True) date = db.DateTimeProperty(required=True)
データを保存したいときには、クラスメンバのput()を呼び出します。データを読み出す場合はall()で全データを読み出せます。
class MainPage(webapp.RequestHandler): def post(self): text = cgi.escape(self.request.get("content")) text = text.replace("rn", "<br>") text = text.replace("r", "<br>") text = text.replace("n", "<br>") if len(text) > 0: com = GuestComment(text=text,date = datetime.datetime.now()) com.put() self.makeHtml() def get(self): self.makeHtml() def makeHtml(self): self.response.out.write(""" <html> <body> <form action="/" method="post"> <div><textarea name="content" rows="3" cols="60"></textarea></div> <div><input type="submit" value="Sign Guestbook"></div> </form>""") comList = GuestComment.all() for com in comList: self.response.out.write('Wrote Date : ') self.response.out.write(com.date) self.response.out.write("<br>") self.response.out.write(com.text) self.response.out.write("<br>") self.response.out.write('<hr>') self.response.out.write('</body></html>')
一部のデータだけを読み出したい場合や、並び順を入れ替えて読み出したい場合にはGQLで指定します。RDBMSで使用するSELECT文とほぼ同様の物なので、すぐに理解できると思います。
comList = GuestComment.gql(“ORDER BY date DESC”)
RDBMSのようにリンクを指定するにはどうするのかって?そこがODBMS独特の部分です。例えばユーザーに関するデータを掲示板への書き込みと同時に保存したい場合、そこにはユーザーを表すクラスへの参照を保存する事になります。ReferencePropertyメンバを使って以下のように記述します。
class UserData(db.Model): name = db.StringProperty() age = db.IntegerProperty() class GuestComment(db.Model): text = db.StringProperty(required=True) date = db.DateTimeProperty(required=True) user = db.ReferenceProperty(UserData)