Google App EngineとPythonができるようになりたかったので、良い参考書がないか探してみたところ、評判の良い本に出会った。
作ればわかる!Google App Engine for Javaプログラミング
- 作者: 中垣健志
- 出版社/メーカー: 翔泳社
- 発売日: 2011/04/23
- メディア: 大型本
- 購入: 3人 クリック: 104回
- この商品を含むブログ (24件) を見る
コード自体はJavaで書かれていたものの、説明がわかりやすい上に面白い題材ばかりなので、これをPythonで作ってみることにした。
(公式サポートサイトにもPythonの記載が一部あるため、利用できるだろうとも踏んだ)
目次
環境
- Windows7 x64
- Google App Engine SDK for Python 1.7.0
- Python2.7
- webapp2
- エディタ
- 作成者
- Google App Engine・Pythonともに入門者レベル、仕事はC#メイン
Pythonで悩んだところと参考ページ
基本的な内容ばかりだけれど、自分が新しく入門した場合、こういうところでつまずくのかと改めて思った次第。
ifとNoneの書き方
今回はNoneを使わなかったけれど、今後の参考として。
- stackoverflow - Python `if x is not None` or `if not x is None`?
- JavaScriptとかPerlとかPHPとかさくらVPSとか勉強する - PythonではNoneの比較は==ではなくisを使う
C#の static みたいなメソッドは何を使えば良いのか?
- クラスメソッド
- スタティックメソッド
の2つあり。クラスに依存するのはクラスメソッド、依存しないのはスタティックメソッドとすればよいのかな?
- 参考
Google App Engineで悩んだところと参考ページ
エラーのハンドリング
今回の場合はwebapp2を利用しているので、以下の2つの方法が取れる。
- app.yamlに、「error_handlers」セクションを追加
- webapp2の「handle_exception」メソッドをオーバーライド
error_handlersではエラーコードがサポートされているとの記載があったものの、サポートされていない場合(ロジックのバグ)はどうなるのか分からず。
実装してみたところ、ロジックのバグでもハンドリングしてくれる上、App EngineのLogにはエラーとして残っていた。
今回の場合、独自処理は不要だったので、前者を利用することにした。
- 参考
webapp2のデバッグフラグの使い分け
開発環境ではスタックトレースを出して、本番環境では出さないようにするには、以下のwebapp2公式ページを参照。
ちなみに、上記のエラーハンドリングをしていると、本番環境でもエラー画面が出たが、それで大丈夫なのかはわからない。
webapp2 - The WSGI application Debug flag
UnicodeDecodeErrorの発生
「'あいう'」と「u'えお'」を結合させた時に発生。先頭に「u」をつけることを忘れずに。
かせきのうさぎさん - 明後日の場所でUnicodeDecodeError
フォルダ構成
css/ +style.css html/ +index.html +index_post.html +error.html __init__.py app.yaml index.py sentence_helper.py
ソースコード
画面遷移は「ドメイン」or「/index.html」でアクセスし、post後は「/submit」とした。
htmlファイルはテンプレートを利用(今回の場合、あまり意味が無い)。
なお、ソースコードのライセンスは本のライセンスに合わせて「Apache 2.0 ライセンス」に。
また、cssファイルは公式ページのモノそのままなので、省略。
GitHubはこちら
https://github.com/thinkAmi/9784798123028_GAE
app.yaml
application: <your application id> version: 1 runtime: python27 api_version: 1 threadsafe: true handlers: - url: /css static_dir: css - url: / script: index.app - url: /index\.html script: index.app - url: /.* script: index.app error_handlers: - file: html/error.html
index.py
#-*- coding: utf-8 -*- import webapp2 from google.appengine.ext.webapp import template import logging import os import sentence_helper class IndexPage(webapp2.RequestHandler): def get(self): self.response.out.write(template.render('html/index.html', {})) def post(self): result = sentence_helper.SentenceHelper.make_sentence(self.request.get('when'), self.request.get('where'), self.request.get('who'), self.request.get('what')) self.response.out.write(template.render('html/index_post.html', {'result' : result,})) # 環境によるデバッグフラグの設定 # See http://webapp-improved.appspot.com/guide/app.html#debug-flag debug = os.environ.get('SERVER_SOFTWARE', '').startswith('Dev') app = webapp2.WSGIApplication([('/', IndexPage), ('/submit', IndexPage), ('/index.html', IndexPage)], debug=debug)
sentence_helper.py
#-*- coding: utf-8 -*- import random class SentenceHelper(object): __whenList = [u'さっき', u'昨日', u'あれはもう3年も昔', u'紀元前', u'ジュラ紀'] __whereList = [u'自宅で', u'近くの居酒屋で', u'世界のまんなかで', u'追い込み中のプロジェクトで', u'木星で'] __whoList = [u'わたしが', u'あなたが', u'オヤジが', u'あこがれのアイドルが', u'神が'] __whatList = [u'新しいソートアルゴリズムを発見した', u'イグノーベル賞を受賞した', u'悟りを開いた', u'こけた', u'十円ひろった'] @classmethod def make_sentence(self, when, where, who, what): when = self.__choice(self.__whenList) if when == '' else when where = self.__choice(self.__whereList) if where == '' else where who = self.__choice(self.__whoList) if who == '' else who what = self.__choice(self.__whatList) if what == '' else what return when + where + who + what @staticmethod def __choice(lists): randomIndex = random.randint(0, len(lists) - 1) return lists[randomIndex]
index.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>イツドコデダレガナニシタ</title> <link href="/css/style.css" rel="stylesheet" type="text/css" /> </head> <body> <form action="/submit" method="POST"> <h1>イツドコデダレガナニシタ</h1> <div class="box"> <dl> <dt>いつ</dt> <dd> <input type="text" name="when" /> </dd> <dt>どこで</dt> <dd> <input type="text" name="where" /> </dd> <dt>だれが</dt> <dd> <input type="text" name="who" /> </dd> <dt>なにした</dt> <dd> <input type="text" name="what" /> </dd> </dl> <p><input type="submit" value="新しい文章を作成する" /></p> </div> </form> </body> </html>
index_post.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>イツドコデダレガナニシタ</title> <link href="/css/style.css" rel="stylesheet" type="text/css" /> </head> <body> <h1>イツドコデダレガナニシタ</h1> <p>{{ result }}</p> </body> </html>
error.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>イツドコデダレガナニシタ</title> <link href="/css/style.css" rel="stylesheet" type="text/css" /> </head> <body> <form action="/index" method="POST"> <h1>イツドコデダレガナニシタ</h1> <div class="box"> <p>エラーが発生しました。</p> <p><a href="index">もう一度やり直してください</a></p> </div> </form> </body> </html>
今後も少しずつ進めていきたい。