search
LoginSignup
10

More than 1 year has passed since last update.

posted at

updated at

Herokuの使い方を勉強した。【Pythonを定期的に自動実行したい】

Pythonを定期実行したかったので、Herokuの使い方を勉強してみました!
 
具体的には、Herokuの公式チュートリアル
Getting Started on Heroku with Python(PythonでHerokuをはじめよう)」

を日本語に翻訳しつつ、勉強した内容をまとめました。

①Herokuの公式チュートリアルを勉強する

Herokuの公式チュートリアルは、「HerokuでPythonプログラムの定期実行」する方法ではないです。

しかし、まず公式チュートリアルをやるとHerokuの使い方がなんとなく分かります。
そして、その後にPythonプログラムの定期実行をやってみるとスムーズに理解できた気がします。

したがって、この記事では「①Herokuの公式チュートリアル」→「②Pythonプログラムの定期実行」の順で書いています。

セットアップ

Gitを使えるようにする。

まず、Heroku CLIを使うには、バージョン管理システムであるGitが必要です。
まだインストールしていない場合は、インストールして設定をします。

Heroku Command Line Interface (CLI)をインストールする。

Herokuのインストーラーはこちらのページから入手できます。

僕はWindowsを使っているので、Windows用のインストーラーの表示に従ってインストールしました。
ScreenShot-2021108_112223.png

インストールが完了すると、コマンドシェルからherokuコマンドを使用可能になります。

Herokuへログインする。

僕はWindowsなので、PowerShellにheroku loginコマンド

$ heroku login

を入力します。

すると、ブラウザが起動して「Herokuにログインしますか?」的な確認画面が出てくるので、受け入れます。
ScreenShot-2021108_11203.png

アプリを準備する

Heroku側が、勉強用サンプルアプリ↓を作ってくれているので

これを自分のローカル環境にclone(コピー)します。

具体的には、まずサンプルアプリを保存したい任意の場所(デスクトップとか)に移動させます。

PowerShellにcdコマンドを入力して移動します。

※例
$ cd 任意の場所

その後

$ git clone https://github.com/heroku/python-getting-started.git

を実行して、ローカル環境にサンプルアプリのクローンを作成します。
「python-getting-started」というサンプルアプリのディレクトリ(フォルダ)が作成されるはずです。

生成されたファイルについて

python-getting-started.png

「python-getting-started」内には、いろいろなファイルが生成されているはずです。

主なファイルの役割↓

  • .env
    環境変数を書いておくファイル。
     「env」は、「environment(環境)」の略。

  • .gitignore
    「.env」などGitの管理に含めたくないファイルを指定するためのファイル。
     (「ignore」の意味は「無視」)

  • app.json
     Herokuでアプリを実行するために必要な環境変数、アドオン、その他の情報を宣言するファイル。

  • manage.py
     Django プロジェクトの設定ファイル。

  • README.md
    説明書的なファイル。

  • Procfile(プロクファイル)
    Heroku上で動かしたいコマンドの一覧を指定するファイル。(拡張子は無し)

  • Procfile.windows
    Windowsでローカル開発を行うためのProcfile(プロクファイル)。

  • README.md
    説明書的なファイル。

  • requirements.txt
    ローカルにインストールしてあるPythonのライブラリを書いておくファイル。
    Herokuへデプロイ時に指定したPythonのライブラリがインストールされる。)

  • runtime.txt
    インストールするPythonのバージョンを書いておくファイル。
    Herokuへデプロイ時に指定したバージョンのPythonがインストールされる。)

アプリをデプロイする

続いて、そのままcdコマンドでディレクトリ(フォルダ)の中へ移動します。

$ cd python-getting-started

そこでheroku createコマンドを実行すると…

$ cd heroku create
Creating app... done, ⬢ serene-caverns-82714
https://serene-caverns-82714.herokuapp.com/ | https://git.heroku.com/serene-caverns-82714.git

みたいな感じで、gitリモート(herokuと呼ばれる)も作成され、ローカルのgitリポジトリに関連付けられます。

アプリにランダムな名前(ここではseren-caverns-82714)になります。

ちなみに

$ heroku create アプリ名

とすると任意のアプリ名を指定できます。
(しかし、数字や大文字始まりのアプリ名や、既に他のユーザー使用されているアプリ名と被っているのはダメっぽいです。)

コードをデプロイする

そのままpush heroku mainコマンドを実行すると、コードをデプロイしてくれます。

$ git push heroku main

実行が終わったらheroku ps:scale web=1コマンドで

$ heroku ps:scale web=1

アプリのインスタンスが、少なくとも1つ実行されているかを確認します。
「now running」みたいなメッセージが返ってきたら成功だと思います。

実際に確認する

次に、先ほどアプリ名で生成されたURL

例
https://serene-caverns-82714.herokuapp.com/ 

でアプリにアクセスします。

ショートカットとして、heroku openコマンドでもWebサイトを開けます。

$ heroku open

こんな感じの画面になっていたら成功だと思います。
ScreenShot-2021108_12932.png

ログの表示方法を知る

公式チュートリアルによると

「Herokuはログを、すべてのアプリとHerokuコンポーネントの出力ストリームから集約された、時間順に並べられたイベントのストリームとして扱い、すべてのイベントに対して単一のチャンネルを提供します。」

とのこと。

…正直、ちょっと何言ってるかよく分からない。笑
「アプリを複数作っても、ログはまとめて時系列順で表示されるよ。」ってことでしょうか。

とりあえずheroku logs --tailコマンド

$ heroku logs --tail

で直近の実行中アプリのログが見れるっぽいです。

Procfile(プロクファイル)を定義する

先ほども紹介した「python-getting-started」の中にある「Procfile(プロクファイル)」。
Heroku 上で動かしたいコマンドの一覧を指定するファイルみたいです。(拡張子は無し)

※Procfileは必ずルートディレクトリに置く。

アプリの拡張

ここまで確認してきたアプリは、"Dyno(仮想サーバー)"上で動作しているみたいです。
いくつの"Dyno"が稼働しているかは、psコマンドで確認できます。

$ heroku ps

"Dyno"は複数使えるので、アプリの負荷が高くなってきたら"Dyno"を増して対応します。
スケールアウトって手法だと思います。)

※"Dyno"の数は、こんな感じ↓で設定・変更する。

$ heroku ps:scale web=1

無料用Dynoと課金について

デフォルトでは、アプリは"無料用Dyno"にデプロイされます。

"無料用Dyno"は、30分ほど活動しないと(トラフィックを受け取らないと)スリープします。
そして、スリープ解除後の最初のリクエストに遅延が生じます。

「そうならない"Dyno"を使いたい場合は課金してね」ってわけです。

※"無料用Dyno"でも使用時間が1000時間/月以上使いたい場合は、課金が必要みたいです。

アプリの依存関係を宣言する

先ほども紹介した「python-getting-started」の中にある「requirements.txt」。
ローカルにインストールしてあるPythonのライブラリを書いておくファイル。

サンプルアプリには

django
gunicorn
django-heroku

が記述されています。
Herokuへデプロイ時に指定したPythonのライブラリがインストールされるみたいです。

ローカル環境にも同じライブラリをインストールしたい場合は

$ pip install -r requirements.txt

で実行できるみたいです。

(上手くいかない場合、Postgresを正しくインストールしてある必要があるみたいです。)

アプリをローカルで実行する

ここらへんは、HerokuというよりDjangoの使い方です。

まず、collectstatic を実行します。

$ python manage.py collectstatic

Djangoの使い方詳しくないので分かりませんけど、必要なファイルを生成するコマンドだと思います。

そして、以下のコマンドを実行します。

heroku local web -f Procfile.windows

(この時に、Windowsでローカル開発を行うためのProcfileである「Procfile.windows」を使うわけですね。)

しばらくすると、ローカルサーバーが立ち上がって「localhost:5000」から先ほどと同じページが閲覧できます。
ScreenShot-2021108_12932.png

ローカルサーバーの停止はCtrl+Cで行えます。

ローカル環境での変更をHerokuに反映させる方法

試しに変更してみる

まず、公式チュートリアル通りにローカルにpythonのライブラリ「requests」をインストールします。
(僕は既に入れてありました。)

$ pip install requests

次に、requirements.txtに「requests」を書き加えます。

スクリーンショット 2021-10-08 164335.png

そして、hello/views.pyを書き換えます。
スクリーンショット 2021-10-08 164443.png
ここにある↑ファイルですね。

requestsをインポートして、関数「index」を指定通りに書き換えます。

views.py
from django.shortcuts import render
from django.http import HttpResponse

from .models import Greeting

import requests # ← 「requests」をインポートする!!!!

# Create your views here.


# def index(request):
#     # return HttpResponse('Hello from Python!')
#     return render(request, "index.html")

# ↓関数「index」を書き換える!!!!!

def index(request):
    r = requests.get('http://httpbin.org/status/418')
    print(r.text)
    return HttpResponse('<pre>' + r.text + '</pre>')

再びローカルサーバーを立ち上げて、localhost:5000 にアクセスすると…

ティーポット画像.png

ページの表示がティーポットのアスキーアートになっています。

変更をHerokuへデプロイ

この状態をHerokuへデプロイします。

まず、変更した全てのファイルをローカルの git リポジトリに追加します。

$ git add .

次に、変更内容をリポジトリにコミットします。
コミットメッセージは「Demo」とします。

$ git commit -m "Demo"

Herokuへデプロイします。

$ git push heroku main

Herokuへデプロイが完了したら、確認します。

$ heroku open

で、アプリのURLへアクセスできましたよね。
アクセスすると…

ティーポット画像.png

ちゃんとティーポットになっていたら成功!

git cloneしない場合

ここまで公式チュートリアル通りにサンプルアプリをgit cloneして進めてきました。

任意のフォルダ内のアプリをHerokuへデプロイしたい場合は

$ heroku create アプリ名

で新規アプリを作った後、
自分でruntime.txt と requirements.txtを用意して

$ git init
$ git remote add heroku https://git.heroku.com/アプリ名.git
$ git add . 
$ git commit -m "コミットメッセージ"
$ git push heroku master

でいけるはずです。

②ファイルの定期実行がしたい

さて。なんとなくHerokuの概念は理解できてきた気がします。

しかし、今回はDjangoで作ったWebアプリをデプロイしたいのではなく、Pythonファイルを定期実行したいわけです。

いよいよ、定期実行をするための設定をしていきたいと思います。

定期実行するファイルを用意する

僕は自分にLINEメッセージを送るプログラムを定期実行させてみます。

LineSend.py
import requests
import datetime

TOKEN = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'  #アクセストークン
# APIのURL(エンドポイント)を変数に代入。
api_url = 'https://notify-api.line.me/api/notify'

# -------------------------------------------
# メッセージを送信する関数
def send_message(send_text, token):
    # 情報を辞書型にする
    TOKEN_dic = {'Authorization': 'Bearer' + ' ' + token}
    # 送りたいコンテンツ
    send_contents = f'{send_text}'
    send_dic = {'message': send_contents}
    # LINE通知を送る(200: 成功時、400: リクエストが不正、401: アクセストークンが無効:公式より)
    requests.post(api_url, headers=TOKEN_dic, data=send_dic)

# 現在時刻を取得
time = datetime.datetime.now()
time = time.strftime('%Y年%m月%d日 %H:%M:%S')

# 送りたいテキスト
send_text = f'\n{time}\nテスト送信'

# メッセージを送信する
send_message(send_contents, TOKEN)

※アクセストークンを発行するためには、LINE Notifyに登録する必要があります。

↓詳しくは、こちらの動画が参考になると思います。

アクセストークンはスクリプトにベタ打ちするのではなく、環境変数に設定した方が良いと思います。

Herokuへデプロイする

先ほどと同じ要領で、用意したpyファイルをHerokuへデプロイします。

(もう一度新たに定期実行用のフォルダを作ってHerokuの設定をしても良いですけど…
とりあえず、練習ならそのまま「python-getting-started」の中に入れると手っ取り早そうです。)

アドオン(拡張機能)を設置する方法

Herokuへデプロイしたファイルの定期実行をするには、「スケジューラ」のアドオンを使います。

まず、スケジューラーを使うには、クレジットカード情報の登録が必要です。
HerokuのAccount settingsBillingタブを開いてクレジットカード情報を登録します。

Billing.png

(※登録したからといってプランを変えない限り、勝手には課金されないみたいです。)

コマンドを使って「スケジューラ」のアドオンを追加します。

$ heroku addons:add scheduler:standard

コマンドを実行して、「Created scheduler-アプリ名」みたいなのが出てきたらOKだと思います。

スケジューラのジョブを設定をする

スケジューラのアドオンを追加したら、ジョブを設定するページへ移動します。

$ heroku addons:open scheduler

を実行すると、ブラウザで設定ページが開かれます。

スケジューラ ジョブの作成.png

Create jobボタンを押して、ジョブを作成します。

定期実行ジョブ.png

ここに実行する間隔と、実行したいpyファイルを設定するわけですね。

設定時は、dyno sizeの「Free」が選択肢に出てこなくて、「え?これ有料のDynoじゃね?」と思いつつ「Standard-1X」にしてみました。
しかし、1度でも実行すると管理画面で「Free」に表示に変わりました。

どうやら、スケジューラで使うdynoは「One-off dyno」というものらしいです。

Free または Hobby dyno タイプを使用するアプリでは、対応する Free または Hobby タイプが One-off dyno で使用されます。その他の dyno タイプは使用できません。

つまり、自分の使用プランに合わせて勝手にOne-off dynoの種類が選択される(?)みたいです。ややこしい…。

最後に、時刻をUTC(協定世界時)で指定します。
(日本標準時から9時間マイナスした時刻になります。)

これで指定通りにプログラムが実行されれば成功です!
(微妙に実行時間がズレるのは仕様のようです。)

今回の場合は、LINEメッセージが来れば成功だと分かりますけど、チュートリアルでやったheroku logsでも情報を確認できます。

参考にさせていただいたページ

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
What you can do with signing up
10