GoogleAppEngineでPython 解析編

2009/10/24 5388hit

前回GoogleAppEngineにアップロードした
HelloWorldの中身を解析してみる。

app.yaml



application: new-project-template
version: 1
runtime: python
api_version: 1

handlers:
- url: .*
script: main.py

app.yamlはyamlと呼ばれる記載方法でプロジェクトの情報が設定されている。
yamlはiniファイルのように直感的で、かつxmlのように階層構造を持つことも出来る記載方法で、
大まかには
設定項目:設定値
と言う形
また、シーケンス(配列のようなもの)を使うときは
- 先頭に置き、 その後の要素はインデントする。


application: new-project-template

application、前回説明したようにGoogleAppEngineのApplication Identifierをセットする。


version: 1

versionにはその名の通り、アプリケーションのバージョンを入力する。
GoogleAppEngineでは一つのアプリケーションに対して複数のバージョンを付けることが出来る。
管理者が実行したいバージョンを好きに変えることが出来るだけでなく、
URLにバージョン情報を入れるだけで、好きなバージョンのプログラムを動かすことも出来てしまう。


runtime: python
api_version: 1

プログラムを動かすランタイムと前提となるAPIのバージョンを記入する。
pythonでやる場合、ここは今のところ変更不可


handlers:
- url: .*
script: main.py

他の部分に比べてチョット特殊で、チョット大切なのがこの部分。
-はシーケンスを表すので
ここではurl: .*とscript: main.pyのシーケンスをhandlers:に渡している。
コレによってアドレス.*に対してmain.pyで処理を行え という意味になる。
つまりは、URLがなんだろうがmain.pyで処理しろという意味。

と言うことで、次は処理が書かれたmain.pyを解析する。

main.py



#!/usr/bin/env python
#
# Copyright 2007 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

import wsgiref.handlers


from google.appengine.ext import webapp


class MainHandler(webapp.RequestHandler):

def get(self):
self.response.out.write('Hello world!')


def main():
application = webapp.WSGIApplication([('/', MainHandler)],
debug=True)
wsgiref.handlers.CGIHandler().run(application)


if __name__ == '__main__':
main()

main.pyは実際のプログラムロジックが書かれている。
内容は複雑だけれども、
GoogleAppEngineアプリをやる上でのおきまり毎みたいなものが多く、とりあえず眺めるだけで良いと思う。


#!/usr/bin/env python
#
# Copyright 2007 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

先頭の#から始まる行はコメント行と呼ばれ
プログラム上何の処理も行わない。
ただし、先頭1行目の

#!/usr/bin/env python

ついてはきちんと入れておかないと動かなくなることがある。

コメント行はプログラムのロジックを分かり易くするために解説を入れることも多い

import wsgiref.handlers

from google.appengine.ext import webapp

GoogleAppEngineを使用するために必要なファイルを読み込んでいる。
ただのimportとfromを含むものの違いは
読み込んだ機能を利用するときにモジュール名が必要かどうかの違い。
fromだとモジュール名を省略することが出来るので google.appengine.ext見たいにモジュール名が長いやつはfromで読み込むと楽

class MainHandler(webapp.RequestHandler):

def get(self):
self.response.out.write('Hello world!')

ページを処理するHomePageクラスを作成している。
Pythonはちょっと面白くて
インデント(字下げ)でブロック構造を記載するようになっている。

上記の例では

class MainHandler(webapp.RequestHandler):

の内容は

def get(self):
self.response.out.write('Hello world!')

同様に

def get(self):

の内容は

self.response.out.write('Hello world!')

C風に中かっこをつけるとこんな感じ
class MainHandler(webapp.RequestHandler):
{
def get(self):
{
self.response.out.write('Hello world!')
}
}

Pythonではインデントがただの飾りではなく
プログラムの処理に大きく影響を及ぼすことに注意


class MainHandler(webapp.RequestHandler):

webapp.RequestHandlerクラスを継承するMainHandlerクラスを定義。

def get(self):

defはメソッドの定義を意味する。
クラス内のget(self)というメソッドを定義している。
webapp.RequestHandlerを継承したクラスのgetはhttpでgetされた時に実行される。

第一引数のselfは、自身のインスタンスを現す。
JAVAでいうthisみたいなもの
関数のメソッドでは、第一仮引数でインスタンスが格納された変数を定義する。
今回はこのメソッドを明示的に呼び出さないので気にする必要がないけれど、この第一引数呼び出す側は記入しなかったりする。
分かりやすいようにselfという変数名にするのが一般的

self.response.out.write('Hello world!')

自身の(RequestHandlerの)response.out.writeメソッドを使って'Hello world!'を出力する。


def main():
application = webapp.WSGIApplication([('/', MainHandler)],
debug=True)
wsgiref.handlers.CGIHandler().run(application)

インデントが

class MainHandler(webapp.RequestHandler):

の行と同じ位置まで上がっており、
ここからMainHandlerクラスから外れる事になる。
defはメソッドの定義なので
main():というメソッドを定義していることになる。
関数のメソッドではないため、第一引数のselfは存在しない。

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

ここではURLに応じてどのクラスを使うかをマッピングしている。
似たような記載がapp.yamlにもあったけれど、app.yamlは処理を行うファイルを指定し。
こっちは処理を行うクラスを指定している。
[とか(については後日
次にdebug=Trueで、debug情報を出力するかを決めている。
今回はdebugを行う設定となっている。

wsgiref.handlers.CGIHandler().run(application)

HTTPに応じて処理が行われる。
ページを開くときはgetで要求されるので
applicationのgetメソッドが実行される。


if __name__ == "__main__":
main()

__name__には
プログラムを開始した名前空間が格納される。
そこがプログラムの開始地点だったら"__main__"が入ることになっている。
if __name__ == "__main__":
main()
上記の場合、(他のモジュールなどからインポートされたのではなくj)スクリプトが直接呼び出された場合のみmain()が実行される。
くどいようだけど、この場合もmain()がインデントされていて
if __name__ == "__main__":の条件に合致する時だけ
main()
が実行されることが分かる。


次回はGoogleAppEngineの仕組みから少し離れて
ぐっと優しくPythonの文法編に行く予定

前:GoogleAppEngineでPython アップロード編 次:Python文法編 if文

関連キーワード

[Python]

コメントを投稿する