今更ながら、「migrate your application to Python 2.7.」って言われてたのに対応してみる

Google App EngineのDashbordを見ると、下記の文言が毎回表示されていた。。。

A version of this application is using the Python 2.5 runtime, which is deprecated! The application should be updated to the Python 2.7 runtime as soon as possible, which offers performance improvements and many new features. Learn how simple it is to migrate your application to Python 2.7.

しかたないので、python 2.7への移行をやってみた。

今回の作業での差分はこちら

基本的には

基本的なことは、
https://developers.google.com/appengine/docs/python/python25/migrate27 に書いてあります。
ただし、英語。。。

というわけで、自分用のメモとして、日本語で。

webapp を webapp2 に変更

importの変更

以前までのwebappを利用しているものは、下記だったはず。

from google.appengine.ext import webapp

それを、

import webapp2

にしました。

WSGIApplication 呼び出し関連の変更

application = webapp.WSGIApplication([('/', IndexPage)
                                      ], debug=True)

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()

とかになっていたところを、

application = webapp2.WSGIApplication([('/', IndexPage)
                                      ], debug=True)

にしました。mainなどはバッサリ削除。

各クラスの定義

class IndexPage(webapp.RequestHandler):

から

class IndexPage(webapp2.RequestHandler):

に。

app.yamlの変更

threadsafe: true

を追記(or 更新)します。

そのまま起動しようとすると、

raise yaml_errors.EventError(e, event_object) google.appengine.api.yaml_errors.EventError: threadsafe cannot be enabled with CGI handler: XXXX.py in "XXXXXX/src/app.yaml", line 56, column 18

とかって表示されてしまうので、app.yaml

handlers:
- url: /XXXX/.*
  script: XXXX.py

から、

handlers:
- url: /XXXX/.*
  script: XXXX.application

に変更します。
application の部分は、webapp2.WSGIApplication を代入した変数名でよいみたいです。

カスタムタグの利用

カスタムタグを利用していたので、

webapp.template.register_template_library('app.templatefilters')

という記述がありました。

  • こちらの解決方法がいまいちわからなかった(setting.pyって何者?とか) and ちょっとやってみたけど、うまくいかなかった
    参考 http://www.john-smith.me/Tag/webapp2
  • そもそも、Djangoが「Web framework」で、webapp2も「lightweight Python web framework」なのに、両方使ってんだ?
  • ここでも、templateエンジンとしてJinja2 が使われている

のため、この際、テンプレートエンジンをJinja2に乗り換えることに。
(名前がかっこいいしw なぜJinjaというの?

Djangoの利用をやめ、webapp2 - Jinja2 にする

Eclipseの設定

PYTHONPATHに、webapp2、jinja2が無いと、

Unresolved import: webapp2

とかっていわれるので、追加する。

すでに、いろいろ追加され、GOOGLE_APP_ENGINE変数も定義されているはずなので、「Add based on variable」を押す。

f:id:suzaku114:20130922202344p:plain

必要なパスを手入力する。

f:id:suzaku114:20130922202401p:plain

追加されてれば、「OK」を押す。

f:id:suzaku114:20130922202412p:plain

app.yaml の編集

libraries:
- name: django
  version: "1.3"

の下2行を削除する。

代わりに、

- name: webapp2
  version: latest
- name: jinja2
  version: latest

を追加。

動かしてみると、

UndefinedError: 'forloop' is undefined

って言われたので、調べたら、これがあったので、

forloop.counter0

が使われていた箇所を

loop.index0

に変更。

カスタムタグを定義していたファイルの変更

app/templatefilters.py に定義し、

register = webapp.template.create_template_register()
register.filter(jst)

としていたのですが、
app/templatefilters.py では、関数の定義のみ行い、 実際のcontrollerの先頭(importの次ぐらい)で、

JINJA_ENVIRONMENT = jinja2.Environment(
    loader=jinja2.FileSystemLoader(os.path.join(os.path.dirname(__file__), 'template')),
    extensions=['jinja2.ext.autoescape'])

from app import templatefilters
JINJA_ENVIRONMENT.filters['jst'] = templatefilters.jst

としました。 (ただ、複数のcontrollerで使うfilterはどこで定義したらいいんだろう。。。)

simplejsonの利用をやめる

from django.utils import simplejson

を使って、jsonのparseやdumpを行っていたので、これも置き換える。

import部分は、下記のように変更。

import json

出力するところは

simplejson.dump(responseJson, self.response.out, ensure_ascii=False)

だったところを

self.response.write(json.dumps(responseJson))

に変更。

パースするところは

data = simplejson.loads(self.request.get('data'))

data = json.loads(self.request.get('data'))

に変更。

レンダリング部分

templateのレンダリング

    folder = 'template'
    path = os.path.join(os.path.dirname(__file__), folder, page)
    html = template.render(path, template_values)
    handler.response.out.write(html)

と、していたので、

    template = JINJA_ENVIRONMENT.get_template(page)
    handler.response.out.write(template.render(template_values))

としました。
フォルダ名は、JINJA_ENVIRONMENT変数を宣言時に設定してあります。

感想

めんどい(最近、こんなんばっかり)
これで、多少ましになった。
あと、pythonの仕組み?がようやく理解できてきた。
ここから機能を追加していきますー。
あと、いいかげんテストを書かないと。テスト無いとこんな作業は恐怖でしかない。