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.
import Vue from 'vue'
import App from './App'
import router from './router'
import axios from 'axios' //axiosを使う場合、main.jsでimportする。
Vue.config.productionTip = false
Vue.prototype.$axios = axios //axiosを使う場合、main.jsでこの行の追記が必要
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})
<template>
<div>
<h1>デモ画面</h1>
<input type="button" value="移動" @click="goNewTask()"> <br>
<input type="number" v-model="message"><input type="button" value="取得" @click="getdata()">
<p> <font size="2"> 入力データ :{{ $data.message }} </font> </p>
<p> <font size="2"> 出力データ :{{ $data.result }} </font> </p>
<p> <font size="2"> 状態 :{{ $data.state }} </font> </p>
</div>
</template>
<script>
// eslint-disable-next-line
/* eslint-disable */
import * as d3 from 'd3' //有効にする
export default {
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.message
this.state="done"
}.bind(this)) //Promise処理を行う場合は.bind(this)が必要
.catch(function(error){ //バックエンドからエラーが返却された場合に行う処理について
this.state="ERROR"
}.bind(this))
.finally(function(){
}.bind(this))}
}
}
</script>
const express = require('express')
const bodyParser = require('body-parser')
const app = 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');
var pyshell = new PythonShell('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)
import sys
data = sys.stdin.readline() #標準入力からデータを取得する
num=int(data)
def sum(a):
return a+3
print(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();
});