FlaskでのCelery　            非同期処理

　
# はじめに
 Flaskで簡単なpythonアプリケーションを作成していました。そこで非同期処理を追加したいと思いました。
しかし、そこでいくつか詰まるポイントがあったため記事にしました。
1つ、先に言えることはpythonでの非同期処理はFlaskではないフレームワークの方が良いかもしれないということです。ググっていると他のフレームワークの方が情報が多く感じました。

# 実行内容
ユーザーがテキストボックスに2つの数字を打ち込み、ボタンを押す。
サーバー側は2つの数字を足し合わせる操作を非同期処理で行い、ユーザーへのレスポンスをすぐ返す。

# 実行環境
os: Windows10
redis Redis-x64-3.0.504.msi

python 3.5.6 (Anaconda)
Flask==1.1.1
celery==3.1.25
redis==2.10.6

# 実行手順
- Anaconda Promptで「python sample.py」を実行する。  
- Anaconda Promptで 「celery -A sample.celery worker -l info」を実行する。
- localhost:9000にアクセスし、テキストボックスに数字を打ち込み、計算実行を押す。
  <img width="958" alt="view.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482108/18fa6493-1272-c266-4b95-7c7433d54bd9.png">

- 結果として、すぐにレスポンスが返る。celeryを実行したAnaconda Promptに計算結果が表示されていることを確認する。
<img width="480" alt="view2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482108/0902d994-eecb-ee66-b7e4-7894f5b66b5e.png">

## つまづきポイント
- celeryとredisのバージョンには相性があるのでまずは、これらを確認する。
 
- redisがlocalhost:6397で動いているか確認する。

- 非同期処理する関数がceleryのtaskに登録されているか確認する。
(「celery -A sample.celery worker -l info」を実行したターミナル上で確認可能)

# おわりに
簡単ですが、以下にsample.py, main.htmlを添付しました。この2ファイルで動きます。参考にしたサイトのURLも添付しておきました。

なにか質問、間違いがあればぜひコメントお願いします。
## ソースコード
```python:sample.py
# coding=utf-8
from flask import Flask, render_template, request

# Flaskアプリ準備
app = Flask("sample")

# this is a part of celery property to use in Flask
from celery import Celery
def make_celery(app):
    celery = Celery(
        app.import_name,
        backend=app.config['CELERY_RESULT_BACKEND'],
        broker=app.config['CELERY_BROKER_URL']
    )
    celery.conf.update(app.config)

    class ContextTask(celery.Task):
        def __call__(self, *args, **kwargs):
            with app.app_context():
                return self.run(*args, **kwargs)

    celery.Task = ContextTask
    return celery

# update flask config to use celery
app.config.update(
    CELERY_BROKER_URL='redis://localhost:6379',
    CELERY_RESULT_BACKEND='redis://localhost:6379'
)
celery = make_celery(app)

@celery.task()
def add(a, b):
    print(a + b)
    return a + b

@app.route('/', methods=["GET", "POST"])
def sample():

    # POST時の処理
    if request.method == 'POST':
        return render_template(
            'main.html',  # 表示するHTMLファイル
            )

    # GET時の処理
    else:
        return render_template(
            'main.html',  # 表示するHTMLファイル
            )

@app.route('/celery', methods=["POST"])
def celery_test():

    if request.method == 'POST':
        a = int(request.form["num_one"])
        b = int(request.form["num_two"])
        result = add.delay(a,b)
        return render_template(
                'main.html',  # 表示するHTMLファイル           
                )

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=9000)
```

```html:main.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8"/>
    <title>Sample</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
  </head>
 
  <body>      
    <div class="container">
      <div class="jumbotron">
        <h1>
          <p align="center">
            <font size="10">Flask 非同期処理</font>
          </p>
        </h1>
      </div>

      <form class="" method="post" action="/celery" enctype="multipart/form-data">
        <div class="container" style="text-align: center;">
          <input type="number" name="num_one">  +  
          <input type="number" name="num_two">
        </div>

        <div class="button_wrapper" style="text-align: center;">
          <button type="submit" class="btn btn-lg btn-success" style="margin-top: 50px; ">計算実行</button>
        </div>

      </form>
    </div> 

  </body>
</html>

```
## 参考文献
Windows版Redisをインストールして触ってみる
 http://kageura.hatenadiary.jp
Flask公式 
 https://flask.palletsprojects.com/en/1.0.x/patterns/celery/
python – Celery Workerを起動できない
 https://codeday.me/jp/qa/20190525/900758.html
celery AttributeError: 'str' object has no attribute 'items' django Day14
 http://www.programmersought.com/article/8120463251/