crontabで設定ファイルが読み込まれない
普段はpythonで仮想通貨の自動取引Botを作ったりしているのですが、息抜きに全く関係ない大学用のTwitterBotを作りました。
このBotは講義が終わるたびにその日の休講情報を呟くものです。
これをcrontabで定期実行させようと考えました。
しかし、設定をしても同じディレクトリにあるアクセストークン等が書かれたjsonファイルが読み込まれない。おかしいと思いログをあさってみると、No such file or directory
。
調べてみるとcrontabのカレントディレクトリがホームディレクトリにあることが原因でした。
解決法
先に解決法を書いておきます。以下のようにコードを変更しました。
- 変更前
f = open("./hoge.json","r") #相対パスでは読み込まれずエラーが起きる
- 変更後
from pathlib import Path
path = Path.cwd() / Path(__file__).parents[0] / "hoge.json"
f = open(path,"r")
原因
crontabのカレントディレクトリはホームディレクトリ
crontabのカレントディレクトリはホームディレクトリであり、スクリプトがあるディレクトリではありません。よって、./hoge.json
のように書くとファイルが読み込まれません。
なぜpathlibを使うのか
異なる環境でも動作する
相対パスでエラーが起きてしまう場合、絶対パスでファイルを参照したりしますが、それだと別の環境下(WindowsとLinuxなど)で使えません。引数でファイルパスを設定するのもありですが、毎回するのは面倒くさいです。
そんな時にpathlibは効果を発揮します。pathlibはPython3.4で追加された公式のモジュールです。
pathlibはパスを表すクラスを提供し、パス通しの連結を/
で行います。
from pathlib import Path
hoge = Path("hoge")
fuga = Path("fuga.py")
print(hoge / fuga)
# > hoge/fuga.py (Linux)
# > hoge\fuga.py(Windows)
パス通しの連結の際に自動的にOSに準拠した表記になり、異なる環境でも動作します。
上位パスにアクセスしやすい
pathlibは上位パスをparents[n]
で取得できます。
from pathlib import Path
path = Path("aaa/bbb/ccc/ddd")
print(path)
print(path.parents[0])
print(path.parents[1])
# > aaa/bbb/ccc/ddd
# > aaa/bbb/ccc
# > aaa/bbb
open()
の引数に使える
pythonでファイルを読み込む場合、大抵open()
が使われますが、この引数にPath()
を使うことができます。(Pytho3.6から)
後は目的のディレクトリまでパスをつなげるだけ
これらを用いれば先に書いたようにパスを指定できます。
path = Path.cwd() / Path(__file__).parents[0] / "hoge.json"
Path.cwd()
はカレントディレクトリを返すクラスメソッドです。
また__file__
はスクリプトの絶対パスを表します。よって、スクリプトと同じ階層にあるファイルを読み込む場合は、Path(__file__).parents[0]
と一つ上の階層のパスを用います。