LoginSignup
81

More than 5 years have passed since last update.

続いてはPython(Flask)でHeroku!

Posted at

どうも。前日のRubyに負けるな!HerokuでPython(Django)動かす方法に触発されて思わず登録してしまいました。kounoikeです。

herokuでmatplotlibでSVGなグラフを書くという記事でもFlask+herokuの導入について触れているのですが、今回はmatplotlib抜きの記事としてみましょう。その代わりに MongoHQ をちょこっと使ってみます。

Flaskとは?

Djangoが「フルスタック」Web フレームワークなら、Flask は「micro」Web フレームワークです。標準の Flask コアは Jinja2 テンプレートエンジンと Werkzeug WSGI ツールキットの2つのライブラリにしか依存していません。提供する主な機能はルーティング、Jinja2 テンプレート、静的ファイルの提供、デバッグ支援くらいでしょうか(すべてを知っている訳ではないので・・・)。もちろん、様々な Flask 拡張ライブラリが提供されているので、もっと凝ったことも色々できるはずです。

.py ファイルが1ファイルで始められる非常にシンプルなフレームワークですので、簡単な Web アプリを作って公開してみたいというときに便利でしょう。

また、昨日の記事を見るに Django では静的ファイルの配信に一手間かかるようですが、Flask では単にstaticの下に置くだけですので js/css/img の配信も楽々です。

まずは簡単に始めてみましょう

heroku のアカウント作成や Toolbelt 導入は済んでるものとします。また、環境は Mac で pyenv, pyenv-virtualenv を導入済みとしています。

heroku の python は 2.7.8 か 3.4.1 なのですが、ここでは 2.7.8 を選択しています。

ライブラリの準備

$ mkdir heroku-qiita-advent-2014
$ cd heroku-qiita-advent-2014
$ pyenv virtualenv 2.7.8 qiita-advent-2014
$ pyenv local qiita-advent-2014
$ echo .python-version > .gitignore
$ pip install flask

テンプレート、アプリの準備

app.py
#!/bin/env python
# coding: utf-8

import os
from flask import Flask, render_template

app = Flask(__name__)
app.debug = True


@app.route('/')
def index():
    return u'テスト'


@app.route('/hello/<name>')
def hello(name=''):
    if name == '':
    ¦   name = u'ななしさん'
    return render_template('hello.html', name=name)


@app.route('/debug')
def debug():
    return render_template('notemplate.html')


if __name__ == '__main__':
    port = int(os.environ.get('PORT', 5000))
    app.run(port=port)

テンプレートファイルは templates/ 以下に置きます。また、静的ファイルはstatic/以下に置きます。

templates/hello.html
<html>
<head>
    <title>Hello {{ name }}</title>
</head>
<body>
    <h1>こんにちは{{ name }}さん</h1>
    <a href="http://flask.pocoo.org/"><img src="/static/img/flask.png"></a>
</body>
</html>
$ tree
.
├── Procfile
├── app.py
├── requirements.txt
├── runtime.txt
├── static
│   └── img
│       └── flask.png
└── templates
    └── hello.html

ローカルで試してみよう

python app.pyとするとローカルホストのポート 5000 でアプリが立ち上がります。/ と /hello/名前 と /debug がありますので試してみましょう。

app.debug = Trueを入れてあるので,http://localhost:5000/debug にアクセスするとエラーページが出ます。

スクリーンショット 2014-12-07 14.05.05.png

heroku にデプロイ

heroku 用のファイルを準備する

$ pip install gunicorn
$ pip freeze > requirements.txt
$ echo python-2.7.8 > runtime.txt
$ echo web: gunicorn app:app --log-file=- > Procfile

git で管理する

$ git init
$ git add .gitignore
$ git add .
$ git commit -m "initial commit"

heroku にデプロイ

$ heroku login
$ heroku apps:create
$ git push heroku master

https://stark-forest-4893.herokuapp.com/ でこのアプリが見られます。https://stark-forest-4893.herokuapp.com/hello/ に続けて適当な名前を入れてみてください。

また、heroku 上だと Flask のapp.debug = Trueは無効になっています。

スクリーンショット 2014-12-07 14.23.55.png

heroku logs コマンドで確認しましょう。

スクリーンショット 2014-12-07 14.23.48.png

データベースを使おう

PostgreSQL の使い方は、英語の記事になりますが、Flask and PostgreSQL on Herokuを参照すると良いでしょう(使ったことないもので・・・)。

なんで使ったことないかと言うと、無料枠は1万行までという制限がきつくて、MongoHQを使っちゃうからです。MongoHQは512MBまでが無料枠です。小さなデータが数多くある場合はこちらの方が使い勝手が良いですね。

MongoHQを使う

色々準備しましょう。

$ heroku addons:add mongohq
$ pip install pymongo
$ pip freeze > requirements.txt

アプリ&テンプレートの修正

app.py
#!/bin/env python
# coding: utf-8

import os
from urlparse import urlparse

from flask import Flask, render_template
from pymongo import Connection


app = Flask(__name__)
app.debug = True

MONGO_URL = os.environ.get('MONGOHQ_URL')

if MONGO_URL:
    # Get a connection
    connection = Connection(MONGO_URL)
    # Get the database
    db = connection[urlparse(MONGO_URL).path[1:]]
else:
    # Not on an app with the MongoHQ add-on, do some localhost action
    connection = Connection('localhost', 27017)
    db = connection['QiitaAdvent2014']


@app.route('/')
def index():
    return u'テスト'


@app.route('/hello/<name>')
def hello(name=''):
    if name == '':
        name = u'ななしさん'
    return render_template('hello.html', name=name)


@app.route('/hello2/<name>')
def hello2(name=''):
    if name == '':
        name = u'ななしさん'

    helloObj = db.hello.find_one({'name': name})
    if not helloObj:
        helloObj = {'name': name, 'count': 1}
    else:
        helloObj['count'] += 1
    db.hello.save(helloObj)

    return render_template('hello2.html', hello=helloObj)


@app.route('/debug')
def debug():
    return render_template('notemplate.html')


if __name__ == '__main__':
    port = int(os.environ.get('PORT', 5000))
    app.run(port=port)
hello2.html
<html>
<head>
    <title>Hello {{ hello.name }}</title>
</head>
<body>
    <h1>こんにちは{{ hello.name }}さん</h1>
    <h2>{{ hello.count }}回目ですね!</h2>
</body>
</html>

https://stark-forest-4893.herokuapp.com/hello2/<名前> で名前ごとにカウントされるようになりました。色々と手抜きですが、サンプルということで。

お次は

kiyotoさんによるfluentd, Postgres, TreasureData 関係だそうです!
fluentd は最近色々と話題ですね。私も興味があります。これらがどう heroku と結びつくのか・・・楽しみです。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
81