Doge log

Abby CTO 雑賀 力王のオフィシャルサイトです

web2pyを使おう!

おはようございます!小倉智昭です!
ちんこうp!ちんこうp!
いやあid:moriyoshiパイプカットするとかしないとかで盛り上がってる中恐縮なんですが今回は
@aodag先生から、アドベントカレンダーが回ってきたのでその話をしたいと思います。

web2py

webフレームワークということなので今回はweb2pyを紹介したいと思います。
正直書くことがなくて困ってたので「ドキッ!漢字だらけのwebサーバ、eurasia」の話を書こうかと
思ったですがやめました。
漢字読めないし。

で話を戻します。
よくpython初心者に使うwebフレームワークなら何がいいですけねー?みたいな話がありますが、
もちのろん答えは決まっています。pyramidじゃなくweb2pyです。
djangoなんて難しいので使ってられません。

web2pyはシンプルにwebアプリケーションを書けるフレームワークです。
シンプルに処理を記述できるため、海外ではそこそこ人気があります。
またドキュメントも整備されています。

web2pyのサイトは以下です。
http://web2py.com/

ここからweb2pyをダウンロードできます。
http://web2py.com/examples/default/download
windows版もちゃんとあります。親切ですね。

では早速起動してみましょう。
1行もコード書いてないですよね?不安ですか?でも安心してください。
動きます。
GUIのツールが立ち上がったらadminのパスワードを入れて、start serverボタンを押しましょう。
初期画面が出てきましたね。

web interface

web2pyの特徴はwebからアプリケーションコードが書けることです。
しかも記述する内容もとてもシンプルで済みます。

adminからアプリケーションを作成、実装してみましょう。
初期画面からclick here for the administrative interfaceをクリックして

http://127.0.0.1:8000/admin/default/site

にアクセスしてみましょう。

左のNew application wizardをクリックすると新しいアプリケーションを作れます。
生成できる雛形をいろいろ編集することができます。
作成したらadminからeditを押して編集できます。

Controllersから新しいContorollerを作成します。
今回はhelloにします。
出来たControllerのeditを押すとエディタ画面に遷移します。
では実装します。といっても最初からコードが書いてあったりします。

# coding: utf8
# try something like
def index(): 
    return dict(message="hello from hello.py")

編集画面ではCtrl-Sを押すと保存できます。
かなり凝ってますね。
次にテンプレートであるViewを作成します。
EDIT APPLICATIONのページに戻り、Viewsからhello/index.htmlを追加します。

{{extend 'layout.html'}}
<h1>{{=message}}</h1>

web2pyではシンプルにメソッド名がurlになります。

http://127.0.0.1:8000/hello/hello/index

にアクセスしてみましょう。
hello from hello.pyと表示できましたか?

最後に

まあざっくり早足で紹介しました。
このおもちゃのようにみえるweb2pyですが、提供している機能はそれなりにしっかりしています。

  1. Form
  2. Validation
  3. Models and Migrations
  4. Cache

また基本的にweb上からなんでもできます。
テストなんかもweb上から走らせられます。すごいですね。

ちょっとしたwebアプリケーションを作成する際に是非使ってみて下さい。
次はid:kuenishi先生にお願いしようと思います。

参考:
web2py - Preface
Google グループ
Google グループ
http://web2py.com/examples/default/videos

omake

Pythonなんてしらねーよ!て人向けにシンプルなwsgiアプリケーションの例をあげておきます。
Python C/APIで拡張モジュールを書くときにMakefile書くとかそーいう嘘情報は無視してください。

setup.py
try:
    from setuptools import Extension, setup
except ImportError:
    from distutils.core import Extension, setup

import os
import sys
import os.path
import platform

def read(name):
    return open(os.path.join(os.path.dirname(__file__), name)).read()


setup(name='hellowsgi',
    version="0.1dev",
    description="",
    long_description=read('README.rst'),
    author='yutaka matsubara',
    author_email='yutaka.matsubara@gmail.com',
    license='',
    platforms='',
    install_requires=[
    ],
    
    entry_points="""

    """,
    ext_modules = [
        Extension('hellowsgi',
            sources=['src/hello.c',],
            )],

    classifiers=[
        'Development Status :: 4 - Beta',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: BSD License',
        'Programming Language :: C',
        'Programming Language :: Python',
    ],
)

hello worldを出してみましょう。

#include <Python.h>

static inline PyObject*
hellowsgi_hello(PyObject *self, PyObject *args)
{
    PyObject *environ, *start_response, *call_args, *status;
    PyObject *headers, *response;

    if (!PyArg_ParseTuple(args, "OO:hello", &environ, &start_response)){
        return NULL;
    }

	if (!PyDict_Check(environ)){
        PyErr_SetString(PyExc_TypeError, "environ must be a dict object");
        return NULL;
    }

    if(!PyCallable_Check(start_response)){
        PyErr_SetString(PyExc_TypeError, "start_response must be callable");
        return NULL;
    }

    headers = PyList_New(0); 
    PyObject *field = PyString_FromString("Content-type");
    PyObject *value = PyString_FromString("text/html");
    PyObject *header = Py_BuildValue("(OO)", field, value);
    
    Py_DECREF(field);
    Py_DECREF(value);

    PyList_Append(headers, header);
    
    Py_DECREF(header);

    status = PyString_FromString("200 OK");
    call_args = Py_BuildValue("(OO)", status, headers);
    Py_DECREF(status);
    Py_DECREF(headers);

    PyObject_CallObject(start_response, call_args);
    
    Py_DECREF(call_args);
    
    response = PyList_New(0); 
    PyObject *o = PyString_FromString("hello world!");
    PyList_Append(response, o);
    Py_DECREF(o);

    return response;
}

static PyMethodDef hellowsgi_methods[] = {
	{"hello", hellowsgi_hello, METH_VARARGS, ""},
	{NULL, NULL} /* sentinel */
};

PyMODINIT_FUNC
inithellowsgi(void)
{
    PyObject *m;
	m = Py_InitModule3("hellowsgi", hellowsgi_methods, NULL);
	if (m == NULL){
		return;
    }
}

C/APIで重要な点はコンテナ系にオブジェクトを突っ込むと参照カウントがあがるという点です。
コンテナがGCで回収された際に中身もろとも消えて欲しいのでコンテナに入れたあと参照カウント下げています。

さてhellowsgiモジュールができました。
走らせてみましょう。

server.py
import hellowsgi
from wsgiref.simple_server import make_server

httpd = make_server('', 8000, hellowsgi.hello)
httpd.serve_forever()