なんだか解りづらいからメモ。
目的
本番サーバで、マルチスレッドで動かす。
開発サーバでも動くようにする。(残念ながらシングルスレッド)
データストアはHigh Replication datastore必須
Python2.7を使う場合、データストアはHigh Replication datastore(HRD)でなければならない。
Master/Slaveで作られたアプリの場合、HRDに移行する必要がある。
HRDへの移行はこの辺を参照。
Administering Your Datastore (Experimental) - Google App Engine - Google Code
http://code.google.com/intl/ja/appengine/docs/adminconsole/datastoreadmin.html
webapp2ライブラリ
webapp2とwebapp2_extrasをアプリのルートディレクトリに置く。
GAE本番サーバでは、google.appengine.ext.webappはwebapp2のエイリアスだけど、開発サーバはwebapp1が入ってる。
webapp1の機能しか使わないのであれば入れなくてもいい。
でもwebapp2.Routeとかの便利機能があるから入れておいたら幸せになれるはず。
Welcome to webapp2! — webapp2 2.3 documentation
http://webapp-improved.appspot.com/
app.yaml
Python2.5の時と書き方が若干違う。
一番解りづらいのはscriptの部分。
threadsafeを有効にした場合、Python2.5のように、/\.py$/を指定すると、以下の例外が発生してアプリを起動出来ない。
Invalid object: threadsafe cannot be enabled with CGI handler: main.py
最初、main.pyをmain.appにリネームすればいいのかなーとか思ったけど全然違った。
以下のようにした場合、main.pyファイルの、変数appを使う、という指定になる。
application: myapp version: 1 runtime: python27 api_version: 1 threadsafe: true handlers: - url: /favicon\.ico static_files: favicon.ico upload: favicon\.ico - url: /.* script: main.app
main.py
app.yamlで指定したように、main.pyにapp変数を作る。
app変数は、webapp2.WSGIApplicationのインスタンスでなければならない。
このapp変数は、グローバル変数として定義する必要がある。
サーバは、このapp変数を複数スレッドで使いまわす。
main()とかはいらない。
example
import webapp2 as webapp class MainHandler(webapp.RequestHandler): def get(self): self.response.out.write('Hello world!') app = webapp.WSGIApplication( [ ('/.*', MainHandler), ], debug=True)
開発サーバで動かない
開発サーバでは、まだPython2.7がサポートされてない。
Warning! The development web server, dev_appserver.py, included in the SDK does not yet support Python 2.7. In order to test your application on Python 2.7 you must deploy it using appcfg.py.
開発サーバを起動してアクセスすると、ImportErrorが発生する。
<type 'exceptions.ImportError'>: Could not find module main.app args = ('Could not find module main.app',) message = 'Could not find module main.app'
開発サーバで動かす
マルチスレッドで動かなくてもいいから、とりあえず開発サーバで表示だけはしたい。
その為に、こうする。
本番サーバでは、main/__init__.pyのapp変数を見に行かせる。
開発サーバでは、main/app.pyを実行させる。
これで両環境「script: main.app」の設定で動く。
main.py を main/__init__.py に移動し、mainをパッケージにする。
main/app.py は main/__init__.py のシンボリックリンク。
mkdir main mv main.py main/__init__.py ln -s __init__.py ln -s __init__.py main/app.py
main/__init__.py
main()とその実行部分を追記。
import webapp2 as webapp class MainHandler(webapp.RequestHandler): def get(self): self.response.out.write('Hello world!') app = webapp.WSGIApplication( [ ('/.*', MainHandler), ], debug=True) def main(): from google.appengine.ext.webapp import util util.run_wsgi_app(app) if __name__ == '__main__': main()
tree
ディレクトリ構成はこんな感じ。
. ├── app.yaml ├── index.yaml ├── main │ ├── __init__.py │ └── app.py -> __init__.py ├── webapp2.py └── webapp2_extras ├── __init__.py ├── appengine │ ├── __init__.py │ ├── auth │ │ ├── __init__.py │ │ └── models.py │ ├── sessions_memcache.py │ ├── sessions_ndb.py │ └── users.py ├── auth.py ├── config.py ├── i18n.py ├── jinja2.py ├── json.py ├── local.py ├── local_app.py ├── mako.py ├── protorpc.py ├── routes.py ├── securecookie.py ├── security.py ├── sessions.py ├── sessions_memcache.py ├── sessions_ndb.py └── users.py
参考URL
Using Python 2.7 - Google App Engine - Google Code
http://code.google.com/intl/ja/appengine/docs/python/python27/using27.html
What's New in Python 2.7 - Google App Engine - Google Code
http://code.google.com/intl/ja/appengine/docs/python/python27/newin27.html