きゃべログ

pythonスクリプトをcronで自動実行したいときに気をつけること

Python

cronでpythonスクリプトを自動実行する場合の落とし穴

最近pythonを使って動画を自動生成して定期投稿をするbotを作ってみました。

botを作るのってもっと簡単なイメージだったのですが、小さなハマりポイントがいくつかあって意外と手こずりました。ということで今回はその情報をシェアしていきます。

ローカルのパス指定は絶対パスで指定する

Pythonスクリプト内のローカルパスを指定するときは絶対パスで記述すると安心です。相対パスで記述すると思った動作をしてくれない可能性があります。

#coding:utf-8

f = open('test.txt','w')

例えば上のようなhoge.pyというスクリプトをcrontabでpython ~/any/path/hoge.pyのようにして実行するとします。するとtest.txtはcrontabを実行しているユーザのデフォルトディレクトリに生成されます。これはcrontabは新たに指定ユーザでログインし、コマンドを実行するためです。

では次のようなスクリプトではどうでしょうか。

#coding:utf-8

f = open('./test.txt','w')

やはりこれでもcrontabのログインシェルのデフォルトディレクトリに生成されます。

補足ですが次にホームディレクトリをした場合にはどうなるでしょうか。

#coding:utf-8

f = open('~/test.txt','w')

この場合はチルダがホームディレクトリに展開されずにエラー終了してしまいます。なのでopen()などでパスを与えるときには/home/[ユーザ名]/のように与えるのが無難だと思います。

新しいLinuxの教科書
新しいLinuxの教科書
posted with amazlet at 16.10.12
大角 祐介
SBクリエイティブ
売り上げランキング: 4,333

pyenvでバージョン管理している場合は気をつける

おそらく多くの方が.bashrcなどで記述しているであろうeval ”$(pyenv init -)“がcrontabでは実行されていないため、pyenvにパスが通っていない状態になってしまいます。そのためpythonはOSプリインストールのpythonで実行されてしまうはずです。そのため想定したバージョンではpipなどでモジュールをインストールしているのにインポート出来ないなどの症状に見舞われます。対応策としては2通りあります。

pyenvにパスを通しちゃう

pyenvにパスが通っていないからデフォルトのpythonが呼び出されているわけなので、通してやれば言い訳です。crontab -eのジョブの最初にパスを通してpyenv initします。サンプルは次のとおりです。

#8時にhoge.pyをpyenvのグローバルバージョンで実行する
* 15 * * * export PYENV_ROOT=$HOME/.pyenv; export PATH=$PYENV_ROOT/bin:$PATH; eval "$(pyenv init -)"; python /any/path/you/want/hoge.py

#15時にhoge.pyを置いてあるディレクトリで指定したバージョンのpythonでhoge.pyを実行する
#こちらはスクリプトがあるディレクトリに移動する必要がある。
* 15 * * * export PYENV_ROOT=$HOME/.pyenv; export PATH=$PYENV_ROOT/bin:$PATH; eval "$(pyenv init -)"; cd ~/any/path/you/want/; python /any/path/you/want/hoge.py

直接pyenv内のpythonを呼び出しちゃう

力技ですが~/.pyenv/versions/下に格納されているpythonを呼び出しても実行できます。そのときのcronジョブの指定は次のようになります。

#15時にpython2.7.9でhoge.pyを実行する
* 15 * * * ~/.pyenv/versions/2.7.9/bin/python /any/path/you/want/hoge.py
ふつうのLinuxプログラミング Linuxの仕組みから学べるgccプログラミングの王道
青木 峰郎
ソフトバンククリエイティブ
売り上げランキング: 140,503

環境変数PATHは指定しなおす

前の話からcronではパスが通っていないことはお察しのとおりですが、これが理由でpython経由でshellのコマンドを実行する場合に使いたいコマンドが見つからないことがあります。たとえば初期設定のままだと/usr/local/bin/にインストールしたコマンドが実行できなかったりします。なのでジョブの先頭にパスを登録するようにしましょう。次は/usr/local/bin/にパスを通す一例です。

#パスを通してからhoge.pyを実行
* 15 * * * export PATH=$PATH:/usr/local/bin/;python /any/path/you/want/hoge.py
実践力を身につける Pythonの教科書
クジラ飛行机
マイナビ出版 (2016-10-26)
売り上げランキング: 66,551

きゃべ (@cab_kyabe)
きゃべ (@cab_kyabe)
Software Engineer / Product Manager