こんにちは、fuyutsuki(@Fuyutsuki)です。
Pythonで業務を効率化できるようになってくると,Pythonスクリプトの実行すらも自動でやりたくなってきますよね。
今回はMacに絞って,指定時間で自動実行する方法について解説します。
Pythonスクリプトで解説しますが,他のプログラミング言語でも問題なく自動化できます。
Windowsではやり方が異なるので,また別の記事で紹介しますね。
Macでの自動化の選択肢
まず,Macにおける代表的な自動化の選択肢であるcronとAutomatorの概要について紹介します。
cron
Mac標準搭載のターミナルにて設定します。MacなどのUNIX系のOSを自動実行するためのものがcronです。一方で,Windowsで自動実行しようとすると,タスクスケジューラを利用しますね。
一般的には次に紹介するAutomaterの方が設定は簡単かと思いますが,プログラミングに慣れている方であればcronの方が設定しやすい可能性があります。
今回の記事ではcronを中心に紹介します。
ちなみに,Hyperというアプリでもターミナルと同様に設定できます。
表示がスタイリッシュなので,私はHyperというアプリの画面で説明します。ターミナルでも全く同じ手順で設定できます。

Automator
こちらもMac標準の自動化アプリです。
LaunchPadから検索してみましょう。

Automatorを起動すると,以下のような画面になります。

画面を見ていただくと分かる通り,ノーコードつまりプログラミングっぽいことをせずに済みます。
プログラミングにまだ慣れていない方はAutomaterの方がおすすめです。
条件分岐も細かく設定できますし,何よりも直感的に設定ができることがメリットです。
Pythonスクリプトを自動で実行したい場合には,上記画像のワークフローを選択すればOKです。
Pythonスクリプトの実行はありませんが,「シェルスクリプトを実行」はあります。

「シェルスクリプトを実行」をクリックすると,直接コマンドを入力できます。
シェルスクリプトの記述方法はこちらのMacのPython環境構築のページが参考になるかと思います。
ここで,Pythonスクリプトを実行する,というスクリプトを書いてあげればPythonスクリプトが自動で実行されます。
Cronでの自動化設定
私はHyperというアプリの画面で解説しますが,ターミナルでも全く同じ手順で設定できるため,便宜上ターミナルの画面という形で解説します。
cronにファイルのアクセス権を付与
実行するプログラムにもよりますが,cronにファイルのアクセス権がないというエラーが出ることがあります。
それを防止するために,cronにファイルのアクセス権を付与します。
システム環境設定>セキュリティとプライバシー>プライバシー>フルディスクアクセスと順番にクリックしていきます。

左下の鍵マークをクリックします。
管理者パスワードを入力し、鍵マークを解除した後,「+」ボタンを押します。
[command] + [shift] + [G]を同時に押すと,フォルダへ移動するための検索バーが表示されます。
下記画像のように,「/usr/sbin/cron」と入力します。

cronのUnix実行ファイルの場所が開きます。
cronが既に選択してあると思いますので,そのまま開くを押します。

フルディスクアクセスにcronが追加されたことを確認しましょう。
確認後,鍵マークをクリックしてロックをかければ完了です。

Pythonプログラムと実行ファイルのパスを確認
まずはcronで設定する際に必要となるため,Pythonプログラムと実行ファイルのパスを確認します。
pythonファイルの場所を確認する際には,下記コマンドをターミナルに入力してEnterキーを押すと良いです。
which python3
Pythonの実行ファイルのフルパスも併せて確認しましょう。
ちなみに,ファイルパスの確認方法としては,Finderを開いて

そうすると,Finderにフルパスが表示されます。

また,ファイルパスをコピーする際にはpythonの実行ファイルを選択して下記のキーボードショートカットでコピーできます。
option + command + C
あるいはファイルを右クリックした後にoptionキーを押すことで,「〇〇のパス名をコピー」というのが表示されるのでクリックすればコピーできます。
この方法で,Pythonの実行ファイルのパスをコピーしておきましょう。
cronの起動と実行プログラム・時刻の設定
まず,ターミナルを開きます。

以下のコマンドを入力してEnterキーを押しましょう。
これでcronが起動します。
crontab -e
以下のような画面が表示されれば,cronが起動しています。

このままでは何も入力できません。
キーボードの”i”を押して,インサートモードに切り替えましょう。

インサートモードになったら,実行するプログラムと自動実行する時刻を設定します。
cron-実行時刻の設定
cronでプログラムを実行する時刻を記述するには下記のような書き方があります。
まず,基本形です。
PATH=/Python3のフルパス/
"分 時 日 月 曜日 実行したいプログラムのフルパス“
※指定しない箇所には * を入れるように。
- 分:0~59
- 時:0〜23
- 日:1〜31
- 月:1〜12
- 曜日:0〜7(0,7=日曜,1=月曜,2=火曜,3=水曜,4=木曜,5=金曜,6=土曜)
- ,:分・時・日などを複数指定する
- -:分・時・日などを範囲で指定する
- /:分・時・日などを間隔で(例:何分毎)指定する
- *:ワイルドカード(全て)
今回は平日のみ15時10分に自動実行すると設定しようと思います。
先程コピーしたファイルパスを基に,下記のようにコマンドを入力すれば設定できます。
10 15 * * 1-5 /Users/project/venv/bin/python3 /Users/project/main_project.py

入力が完了したら,「escキー」を押してコマンドモードに切り替えた後,「:wq」と入力して,Enterキーを押します。
これで元の画面に戻りますので,設定完了です。
元の画面に戻った際にこのようなエラーコメントが表示された場合は,何かしら文法が間違っています。

半角スペースの入れ方などが正しいか,再度見直しましょう。エラーコメントが表示されても,yを入力すれば再度設定できます。
cronが設定できたかどうかの確認
cronが正しく設定できたかどうかを確認するには,ターミナルで下記のコマンドを入力し,Enterキーを押しましょう。
crontab -l
設定したcronコマンドが表示されればOKです。
ここで,crontabのコマンドを整理しておきましょう。
- crontab -e:crontabの設定の登録・編集
- crontab -l:設定したcrontabの確認
- crontab -r:設定したcrontabを削除
- crontab -u:ユーザーを指定
cronが実行されたかどうかの確認
cronが実行されたかどうかを確認するには,ターミナルで下記のコマンドを入力し,Enterキーを押しましょう。
less /var/log/cron
あくまでここでしていることは,実行ログが残っているかの確認です。
あるいは,プログラム開始のタイミングでメールを送るようにpythonプログラムを記述しても良いかもしれません。
例えば,以下のようにmain.pyとsend_mail.pyを同一フォルダに用意しておくと,main.pyのSendMail().send_mail_test(test)関数を実行しておくことで,プログラム開始時にgmailが届きます。
- main.py
from send_mail import SendMail
if __name__ == '__main__':
# 処理開始メッセージ
test = 'プログラム処理開始'
SendMail().send_mail_test(test)
# 〜〜自動実行する処理を記述〜〜
- send_mail.py
from email import message
import smtplib
import datetime
from tabnanny import check
import smtplib
from email.message import EmailMessage
class SendMail:
def __init__(self):
# メールの設定
self.SMTP_HOST = 'smtp.gmail.com'
self.SMTP_PORT = 587
self.FROM_ENAIL = 'XXXXXXXXX' #送信者
self.TO_EMAIL = 'XXXXXXXXX' #宛先
self.USERNAME = 'XXXXXXXXX' #gmailアドレス
self.PASSWORD = 'XXXXXXXXX' #gmailアドレスのパスワード
self.nowdate = datetime.datetime.now().strftime('%Y年%m月%d日')
def send_mail_test(self,text):
#メッセージ内容_alert
self.msg = EmailMessage()
self.msg.set_content(text)
self.msg['Subject'] = self.nowdate + '_' + 'プログラム開始'
self.msg['From'] = self.FROM_ENAIL
self.msg['To'] = self.TO_EMAIL
self.msg.add_alternative(text, subtype='text')
self.msg.add_alternative(text, subtype='html')
with smtplib.SMTP(self.SMTP_HOST, self.SMTP_PORT) as smtp:
smtp.starttls()
smtp.login(self.USERNAME,self.PASSWORD)
smtp.send_message(self.msg)
環境変数の設定
python実行ファイルに相対パスを使用している場合は,カレントディレクトリを修正する必要があります。
pythonの仮想環境の構築についてはこちらの記事で解説しています。
バッチファイルを作成する際のpip installにpython-dotenvを追加しましょう。
pip install python-dotenv
Node.jsを記述する際にもよく使われる手法ですが,.envファイルとconfig.pyを別途作成します。.envファイルには設定したいカレントディレクトリ(main.pyのフルパス)を記述し,それをconfig.pyで読み込みます。最後に,main.pyでconfig.pyで読み込んだ環境変数を使えば良いです。
それぞれのファイルは同一フォルダに配置しておけば問題なく動作します。それぞれ下記のように記述しましょう。
- .env
CWD = 'XXXXXXXX' # カレントディレクトリのパス(main.pyのフルパス)を記述
- config.py
from dotenv import find_dotenv, load_dotenv
import os
load_dotenv(find_dotenv())
CWD = os.environ.get('CWD')
- main.py
import config
import os
os.chdir(config.CWD) # カレントディレクトリを変更する
print(os.getcwd()) # 正しく設定できたか確認する
スリープモードを自動で解除
cronにしろ,Automatorを使うにしろ,スリープモードになっていると指定時刻が来てもプログラムが実行されません。
システム環境設定>省エネルギー>スケジュールへと進み,起動またはスリープ解除を設定します。
プログラムを実行させる数分前には起動させておいた方が良いでしょう。

まとめ
今回の記事では,MacのcronでPythonを時間指定で自動実行する方法について画像付きで徹底解説しました。
プログラミングに慣れていない方でも今回の記事を見ればcronの設定ができるかと思います。
自動化できるものはガンガン自動化して,時間を作り出しましょう!
また、デスク環境についての記事を最近はまとめているので、良ければチェックしてみてください。
最後まで読んでいただきありがとうございました,ではまた次の記事で!
コメント