我要訂便當 (4): 將 Python 腳本部署上 Heroku
2024.10 更新: Line Notify 將於 2025 年 3 月停止服務(LINE Notify 結束服務公告),有看到這篇的朋朋請選擇一組新的通知服務來串吧 QQ
目標:紀錄一下如何將 Python 寫好的東西丟上 Heroku
在先前的 訂便當系列 中已經建立了一個替我們去爬便當網並通知我們的小工具,但還存在一個相當大的問題:要在哪跑?總不能就只放在家裡電腦有開機就跑、沒開機就算了吧?因此我們必須找個主機把它放上去。而在上一篇做 Line Notify 的時候所參考的 如何快速建置一個 LINE Notify 的服務 中提到了將服務放上 Heroku 的部分,因此馬上嘗試看看。
結果過程中碰了不少壁,因此特地紀錄下來。
Heroku 是一個雲端平台,讓使用者可以把服務丟上去跑,同時最讚的部分是,免費用戶就提供了每月 450 小時可以使用(但有每半小時會進入休眠的限制),詳情可以參閱 Heroku 的計費頁面。
更新:Heroku 已經改為收費方案了 QQ
本系列最後一階段的目標就是要將訂便當爬蟲整套丟上去雲端上運行,達到被動接收通知的效果。但由於訂便當爬蟲還牽涉到用 Selenium 開瀏覽器互動,以及使用 Sqlite 儲存的部分,轉移到 Heroku 的環境上還需要進行一些調整。因此這一階段將會分成兩篇(或以上)文章進行,上篇會先簡單地紀錄如何將服務放上 Heroku,下篇開始則著重於紀錄將訂便當系統放上 Heroku 時遇到的問題和解決過程。
本篇主要的參考來源來自於 搭配 Git 在 Heroku 上部署網站的手把手教學、發布網站到 Heroku 以及 網站部署(使用 Heroku) 這幾篇,其餘參考將附於文末,感謝各位前人大大留下的優質文。
註冊及安裝
Heroku 的 註冊 相當簡單,這邊就略過不提,需要說明可以參考 這篇。
註冊完畢就會回到個人頁面,底部有 Heroku Dev Center,也能選自己慣用的程式語言進去教學說明,有興趣的可以逛個一圈。
這邊我們就先新增一個應用程式,點選畫面中間左側的 Create a new app
接著輸入應用程式名稱,注意只能使用小寫,並且不能重複。如果已經使用後續會提到的 CLI 的朋友,也可以直接使用 heroku create
的指令來建立應用程式。
建立完成之後就會進到專案的頁面:
可以看見 Heroku 提供了幾種方法來將應用程式推送到 Heroku 上,例如連接到 Github。我們這邊用 Heroku CLI 試試,頁面上也已經提供了步驟說明。
Heroku CLI 的安裝說明頁面,在這邊挑選自己的系統下載並安裝。
安裝過程也相當簡易,會有將 Heroku 加到環境變數和路徑等選項,一路下一步即可。
裝完之後,打開命令列輸入 Heroku,如果有跳出指令列表就代表安裝已經成功
連接至 Heroku
備註:由於 Heroku 傳送檔案的方式是使用 Git 進行,因此在後續的操作之前,必須先確保電腦中已經安裝 Git
接著我們就按照上面 Heroku CLI 說明頁面的步驟開始操作。
首先要先登入,輸入 heroku login
之後,便會開啟瀏覽器進行登入驗證,如果成功會看見登入訊息
接著就可以移到專案的資料夾,將專案和 Heroku 做連接
# 先移動到專案的資料夾
$ cd my-project/
# Git 初始化
$ git init
# 和 Heroku 專案連接
$ heroku git:remote -a Heroku的APP名稱
環境設定及測試
這邊由於前面提到訂便當系統有部分要調整的關係,因此只使用 我要訂便當(3) 的 Lint Notify 測試版 的 Line Notify 上去試試看。上一集的簡單 Line Notify 程式碼如下,這邊命名為 myApp.py
:
import requests
def lineNotifyMessage(token, msg):
headers = {
"Authorization": "Bearer " + token,
"Content-Type": "application/x-www-form-urlencoded"
}
payload = {'message': msg}
r = requests.post(
"https://notify-api.line.me/api/notify",
headers=headers,
params=payload)
return r.status_code
message = 'Line Notify + Heroku 測試'
token = 'YOUR TOKEN'
result = lineNotifyMessage(token, message)
接著除了主要的 py 檔以外,還需要一些檔案去告訴 Heroku 怎麼處理我們的服務。
事實上我第一次是直接就把 py 傳上去 Heroku 然後建置大失敗,還好 Google 了一陣有前人指點,這邊的設定部份參照自 如何使用 Heroku 部屬一個 Web App 網頁應用程式,特此感謝。
不過 Heroku 還不知道怎麼建我們的服務,因此這邊還需要新增幾個設定的檔案:
Procfile
用來告訴 Heroku 怎麼運行我們的服務
worker: python myApp.py
這行的意思是:worker
的運行方式是 python myApp.py
這行命令,Heroku 會根據這個文件的內容去建 dynos 容器來運行我們的應用服務。
像上面的參考文章在建置 Flask 時,就將運行 web
的命令設定為 gunicorn flask_app:app
讓 Gunicorn 去起網站來跑。
由於這次的示範組只是個小腳本,因此我們宣告個 worker 而不是網站方便之後處理。當宣告的運行是 web
時,Heroku 還會幫忙接 HTTP 的內容,當然想包裝成 Web APP 的朋友,也可以參考上面的文章將腳本包裝成簡單的 Flask。
關於 Procfile 和 dynos,可以參見 Heroku 運行類別、 Procfile、常用指令筆記 以及 Heroku 官方的 Dynos (app containers)
這邊另外要注意的地方有兩個:這個檔案是不需要副檔名的,而且大小寫請正確。我在碰壁的過程中有遇到本機測試可以但推送上去就不行的情況,後來發現是打成全小寫了,改成字首大寫就正常,因此這邊提醒一下大家。
requirements.txt
用來標示需要安裝的套件,逐行列出套件即可,也可以用 套件名稱==版本號
的方式指定套件版本。由於測試的程式碼只用到 requests,因此這邊列上 requests 就可以了。
requests
runtime.txt
用來標示 Python 的版本,這篇文當下的版本為
python-3.7.6
本機測試
到目前為止沒意外的話應該會包含這些東西
這邊可以嘗試在本機測試看看,打開命令列輸入 heroku local worker
就可以在 localhost Run 起來看看囉。注意這是在本機啟動 worker 這個 dynos 的意思,所以如果前面的 Procfile
是使用 web 的朋友,這邊就要輸入 heroku local web
囉。
想要全面啟動,可以直接輸入 heroku local
;想要指定 Port 的也可使用 heroku local -p 7000
等等,可以參見 Heroku 運行類別、 Procfile、常用指令筆記 的啟動段落有比較常用的用法。
如果一切安好,就可以開始嘗試部署囉
部署至 Heroku
Heroku 的部署只需要用 Git 推送上去就可以了,也就是只需要
# 把所有檔案都加到這次變更
$ git add .
# Commit 所有變動(記得標註解,養成好習慣)
$ git commit -am "這是Commit註解"
# 推送
$ git push heroku master
就可以發到 Heroku 進行部署了,推送時也能看見建置的過程,如安裝的包和建置是否成功等資訊都會顯示
如果前面架上去的是網站,也就是 Procfile
使用 Web 的朋友,Heroku 應該會幫忙把服務建起來。而像我是另外定義 worker
的朋友,這邊還需要多一個把 dynos 建起來的動作
命令列中輸入 heroku ps
就可以看到現在正在運行的服務,如果沒有任何服務運行,或是想擴展服務,可以使用 heroku ps:scale Procfile裡定義的服務=服務數
來操作。
例如我是使用 worker,這邊就輸入 heroku ps:scale worker=1
就會開啟一個 worker 來運行;反過來說,輸入 heroku ps:scale worker=0
就可以停止 worker 的服務囉。
如果這邊部屬和運行有問題的朋友,可以查看 Heroku 的 Log:在命令列輸入 Heroku log
就會顯示了(建議搭配 --tail
等方法使用,詳請可見 官方文檔)
此外,若是跟我初嘗試一樣跑出 Couldn't find that process type
請參照 這篇,我個人是修改 Procfile
檔名的大小寫就解決了
若是建置時無法成功的朋友,可能是沒抓到你的服務的語言(例如 Python),需要自己去拉一下 buildpacks,例如 Python 的建置包就是 heroku-buildpack-python
最後我們回來看一下 Heroku 的 APP 頁面
Activity
可以看見最近的活動,例如部署失敗也會顯示在這;而 Settings
則是一些專案設定,例如名稱和建置包都要到這裡調整
其中可以從 Domains
這裡連到你的服務,如果你放的是網頁或 API 的話就可以從這裡進入。不過更快進入自己服務的方法,是在命令列中直接下 Heroku open
就行啦。
後記
其實原本打算部署的部分一篇解決的,沒想到牆就這樣撞了上來,將便當放到 Heroku 上時實在遇到挺多問題,例如第一次使用時直接把整坨檔案直接推上去也沒設定結果建置失敗,或是發現 Heroku 不給用 Sqlite,或是 Selenium 要另外找建置包等等,因此最後決定切成兩篇,一篇好好記 Heroku 的流程,剩下的部份再按照問題做紀錄。
同時因為原本的訂便當已經在家裡電腦跑著了,部屬上雲似乎是額外再戰的部份。待到剩下問題解決了,抓緊下班時間再寫上來記著,希望以後能派上用場吧。
我要訂便當系列
- 我要訂便當(1) —— 用 Python + Selenium 控制瀏覽器取得訂單
- 我要訂便當(2) —— 用 Python + Sqlite 儲存訂單
- 我要訂便當(3) —— 用 Python + Line Notify 傳送通知
- 我要訂便當(4) —— 將 Python 腳本部署上 Heroku
- 我要訂便當(5) —— Heroku 填坑小記
參考資料
- 搭配 Git 在 Heroku 上部署網站的手把手教學 - 神Q超人
- 第十八天:發布網站到 Heroku - 只要有心,人人都可以做卡米狗
- 網站部署(使用 Heroku) - 為你自己學 Ruby on Rails
- 如何使用 Heroku 部屬一個 Web App 網頁應用程式 - TechBridge 技術共筆部落格
- [Golang][LINE][教學] 如何快速建置一個 LINE Notify 的服務 - KKDAI.GITHUB.IO
- Python Django 學習紀錄(九) 部屬網站到 Heroku - IvanKao的部落格
- 用 Heroku 部署網站 - Django Girls Taipei
- Heroku 運行類別、 Procfile、常用指令筆記
- Python PIP 使用 requirements.txt 管理套件相依性
- Heroku-buildpack-python
- Heroku Dev Center
- Heroku Dev Center: Getting Started on Heroku with Python
- Template for hosting python scripts and applications on Heroku - Github
其他文章
哈囉,如果你也有 LikeCoin,也覺得我的文章有幫上忙的話,還請不吝給我拍拍手呦,謝謝~ ;)