自作のポートフォリオをLaravelで制作中にPythonのライブラリを使って処理を実行したかったので、挑戦してみました。
いくつかのつまづきポイントがあったのでまとめ
開発環境
PHP(8.0.2)
Laravel(9.19)
Python(3.8.10)
Pythonの実行はexec関数
PythonをLaravel上で使用するのに、いろいろ調べたところ、PHPのexec関数で実行できるということでした。
まずはPythonファイルを作成。
私はappディレクトリ内にpythonディレクトリを作りその中にファイルを作りました。
import sys
import pandas_datareader.data as web
code = sys.argv[1]+'.T'
start_date = sys.argv[2]
start_open_or_close = sys.argv[3]
end_date = sys.argv[4]
end_open_or_close = sys.argv[5]
df = web.DataReader(code, 'yahoo', start_date, end_date)
start_price = df.loc[start_date,start_open_or_close]
end_price = df.loc[end_date,end_open_or_close]
yield_price = end_price - start_price
yield_ratio = round(yield_price/start_price*100,1)
high = df['High'].max()
low = df['Low'].min()
print(start_price)
print(end_price)
print('{:+}'.format(yield_price))
print('{:+}'.format(yield_ratio))
print(high)
print(low)
今回はpandas_datareaderライブラリを使って、コードと日付を受け取り、株価等を返したかったので、
①ライブラリをインポート
②sys関数で引数をとる
③実行メソッドを書く
④print関数で出力
を行いました。
そしてLaravelのControllerでexec関数を使いPythonファイルを実行し、返ってきた値をsessionに入れています。
public function start(Request $request)
{
$request->validate([
'code' => 'required | numeric',
'start_date' => 'required | date | before_or_equal:today | before_or_equal:end_date',
'end_date' => 'required | date | before_or_equal:today | after_or_equal:start_date',
]);
$path = app_path() . "/python/test.py";
$code = $request->code;
$star_date = $request->start_date;
$start_open_or_close = $request->start_open_or_close;
$end_date = $request->end_date;
$end_open_or_close = $request->end_open_or_close;
$command = "/usr/bin/python3 " . $path . " $code" . " $star_date" . " $start_open_or_close" . " $end_date" . " $end_open_or_close";
exec($command, $output);
if (empty($output)){
return back()->withInput()->with('no_data', '銘柄コード、日付を正しく入力してください');
}
$result = [
'start_price' => $output[0] ,
'end_price' => $output[1] ,
'yield' => $output[2] ,
'yield_ratio' => $output[3] ,
'high' => $output[4] ,
'low' => $output[5] ,
];
$inputs = $request->except('_token');
$request->session()->put($inputs);
$request->session()->put($result);
return view('analyze.result');
}
これで銘柄コードと日付を渡せば株価や暴落率が返ってくる。
問題はここからです。
pip問題
ローカル環境では動作するのに、コンテナ内では上手く返ってこない。
原因はLaravel sailのdockerコンテナ内にpythonはインストールされているものの、pipがインストールされていなかった。
そこでコンテナ内に入ってpipをインストールしようとしました。
sail shell
そこでaptを実行しようとしても権限エラー
sail root -shell
でルートユーザーでログインできたので、
apt update
apt upgrade
apt install pip
で解決。
そして必要なライブラリをpipインストール
docker fileの編集
コンテナ内で直接pipとライブラリをインストールしてもコンテナを停止して再開したら消えています。
そこでdocker fileを編集しました。
sail artisan sail:publish
でルートディレクトリにdockerファイルの入ったディレクトリが出現。
そこにapt-getのところにpipを追加。
さらに、
RUN pip install ライブラリ名
を追加。
sail build --no-cache
でコンテナを再構築すれば、毎回コンテナに入ってインストールしなくて済みました。
aws内でのエラー
awsにデプロイする際にもつまづきがありました。
デプロイ後値がなにも返ってこない。
ひも解いていくと、PythonファイルでModuleNotFoundErrorとなっていました。
pipインストールしてpip listで確認してもインストールされているのに。
どうやらimportする際の探しにいくpathが問題のようで、
sudoをつけてpipインストールすると解決しました。
これについてももう少し調査の必要があります。
まとめ
言語の組み合わせはなかなか情報が少なくて難しい。
なかなかハードルが高く、無理やりな部分もありますが勉強になりました。