1.目的
・Vue-CliとPythonの連携を図りたい。(Vue-CLiを使ったアプリ上でPythonを動作させたい)
2.方法
・フロントエンドはVue-Cliで構成する。Pythonコードはバックエンドに配置する。
・Vue-CliとPythonとのインターフェースはPython-shellを使う。
・フロントエンドとバックエンドはそれぞれ別のポートを割り当て、双方が通信できるようにする。
3.環境設定/準備
使用したパッケージやライブラリのインストール方法やversionを下記に記載しておきます。
項目 | version | インストール方法 |
---|---|---|
Vue-Cli | 3.9.3 | LINK先を参照 |
python-shell | 1.0.8 | LINK先を参照 |
express | 4.17.1 | |
bodyparser | 説明略 | |
node.js | 12.14.0 | 説明略 |
npm | 6.3.14 | 説明略 |
4.作成したアプリ
Webページより、入力した値に+3を加算し、その演算結果を表示します。
★上記図中の(1)~(6)は、下記に説明する動作(1)~(6)に対応しています。
(1)「デモ画面」数値をテキストボックスに入力します。
(2) 取得ボタンをクリックします。
(3) (1)で入力した数値がindex.js(Python-shellを実行する)を介して、Pythonコード(sample.py)に送られます。
(4) sample.pyは、入力された数値に+3を加算します。
(5) sample.pyは、演算を完了した数値をindex.jsに返却します。
(6) index.jsは、sample.pyから受け取った数値を「デモ画面」に返します。
(7)「デモ画面」は、演算結果を表示します。
4-1 システム構成
Vue-Cliはすでにインストールされ、使用できる状態であるという前提です。
4-2 ディレクトリ構成
各ファイルのディレクトリ構造は下記のとおり配置されています。
4-3 コード
// eslint-disable-next-line/* eslint-disable */// The Vue build version to load with the `import` command// (runtime-only or standalone) has been set in webpack.base.conf with an alias.importVuefrom'vue'importAppfrom'./App'importrouterfrom'./router'importaxiosfrom'axios'//axiosを使う場合、main.jsでimportする。Vue.config.productionTip=falseVue.prototype.$axios=axios//axiosを使う場合、main.jsでこの行の追記が必要/* eslint-disable no-new */newVue({el:'#app',router,template:'<App/>',components:{App}})
<template><div><h1>デモ画面</h1><inputtype="button"value="移動"@click="goNewTask()"><br><inputtype="number"v-model="message"><inputtype="button"value="取得"@click="getdata()"><p><fontsize="2">入力データ :{{$data.message}}</font></p><p><fontsize="2">出力データ :{{$data.result}}</font></p><p><fontsize="2">状態 :{{$data.state}}</font></p></div></template><script>// eslint-disable-next-line/* eslint-disable */import*asd3from'd3'//有効にするexportdefault{name:'top',data:function(){return{message:'',//入力データを格納する変数。result:'',//演算結果を格納する変数。state:"wait"//現在の状況を格納する変数。}},methods:{//テキストボックスに入力されたデータをバックエンドに送り、バックエンドから演算結果を受け取り、その結果を表示するメソッドgetdata:function(){this.state="getting data"this.$axios.get('http://192.168.0.4:3000/api',{params:{dat:this.message}}).then(function(response){console.log(response.data.message)//バックエンドから返却された演算結果をconsole.logしている。this.result=response.data.messagethis.state="done"}.bind(this))//Promise処理を行う場合は.bind(this)が必要.catch(function(error){//バックエンドからエラーが返却された場合に行う処理についてthis.state="ERROR"}.bind(this)).finally(function(){}.bind(this))}}}</script>
constexpress=require('express')constbodyParser=require('body-parser')constapp=express()app.use(bodyParser.json())//CORSポリシーを無効にしている。app.use(function(req,res,next){res.header("Access-Control-Allow-Origin","*");res.header("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept");next();});app.get('/api',function(req,res){var{PythonShell}=require('python-shell');varpyshell=newPythonShell('sample.py');console.log("req")console.log(req.query.dat)//フロントエンドから受け取ったデータをconsole.logしている。pyshell.send(req.query.dat);//本コードからpythonコードに'req.query.dat'を入力データとして提供する //pythonコード実施後にpythonから本コードにデータが引き渡される。pyshell.on('message',function(data){console.log("return data")res.send({message:data//pythonで実施した演算結果をフロントエンドに返している。})})})app.listen(3000)
importsysdata=sys.stdin.readline()#標準入力からデータを取得する
num=int(data)defsum(a):returna+3print(sum(num))#printの内容をpython-shellに返却する
4-4 実行方法
5.ポイント
5-1 Pyshon-shellを使用した理由
Vue-cliはwebpack上で動作していますが、python-shellは、webpack上では動作しないようです。よって、新たにvue-cliで動作させていないサーバーを立ち上げその上でpython-shellを動作させるようにしました。
5-2 CORS問題の回避方法
xxx.xxx.xx.xx:91 から xxx.xxx.xx.xx:3000にアクセスする場合、ドメインが異なるのでセキュリティー上通信がブロックされます[CORS問題]。CORS問題を避けるために、アクセスする側に対策を施す場合と、アクセスされる側に対策を施す場合があるが、本件ではアクセスされる側に対策を施しました。詳しくはこちらをご覧ください。
/bkend///CORSポリシーを無効にしている。app.use(function(req,res,next){res.header("Access-Control-Allow-Origin","*");res.header("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept");next();});