Python
JavaScript
bottle
Vue.js
Electron

Electron+Vue.js+Python(Bottle)でhttp requestを取得

More than 1 year has passed since last update.

読むの面倒という人はgithub repositoryにアクセスしてgit cloneして動かそう!

https://github.com/bluelief/pyelectron


はじめに

誰しもが思うpythonでGUIを作りたい。そう・・・作りたい。作っちゃいたい。ただQtはライセンス的によく分からないから習得したくない、kivyは流行りみたいだけどUIが正直微妙。王道のwxPythonが一番の有力候補だったのだけれども、Electronキテるっぽ??

一度はElectron触ってjavascript以外との親和性が絶望的なように感じ諦めたのだけれども、作っていくうちに意外とPythonは耐えうるような気がしたので成果物を公開しようと思った次第です。

サンプルは極力余分なものを排除し必要な機能のみ記述しています。


まずは余談から

5/24/2018 修正:Electronの採用アプリケーションについて勘違いしていました。

AtomやVSCodeでElectronが使われ、何よりFirefox, ChromeでElectronが採用され爆速になってから非常に興味を持っていた。が、しかし!Atomのgithubを見るとほぼ.jsで構成されており、javascriptが未だにステータスバーやwebサイトのぴかぴか、アラートなどに使われる言語という認識でしかないため、

正気か?!

狂気の沙汰・・・。

それでもトレンド的に少しいじったりコピペして動いたら勝ちみたいなところから卒業せねばと思っていたので勉強がてら着手してみたような感じです。だいたい3日くらいjavascriptの迷路で迷子になっていました。


そろそろ本題に

vueを選んだのはzerorpcがインストールできないため、他人のプロジェクトが真似できなかったのと、javascriptは基本のifとか程度しか知らずvueを学んだため、むしろvue以外でやれと言われるとできないという。


1. 準備


nodejs install

node -v

v8.11.2

npm -v
5.6.0


npm package install

git clone https://github.com/bluelief/pyelectron.git

cd pyelectron
npm install


とりあえず動かしたい人

package.jsonにscriptsという項目があり、そこに登録しているコマンドが動かせるようです。makeとかbatファイル作らなくてよいので結構便利。

# start the program

npm run start

# build the package

npm run package-win


2. 解説


主要 index.js

まずはElectronのbackendとして動かすためにpython scriptをchild_processで動かす。


index.js

const createPyProc = () => {

//Important. Must to get full path.
script = path.join(__dirname, 'main.py')
pyProc = require('child_process').spawn('python', [script])
}

閉じたときのClose process


index.js

const exitPyProc = () => {

pyProc.kill()
pyProc = null
pyPort = null
}

Window生成の部分。コメントしているところをコメントアウトするとデバッグモードで動きます。

他の人と違うとすれば最初の読み込みはindex.htmlにしているところかな?プログラム起動時からPython serverにアクセスすると重いというのと、pythonは処理のみにしてfront-endはhtmlでいいような気がしたためです。


index.js

function createWindow () {

mainWindow = new BrowserWindow({ width: 800, height: 600,
useContentSize: true, resizeable: false })
mainWindow.center() // 起動時windowをセンターに
mainWindow.setResizable(false) // ウィンドウのリサイズを禁止
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'), // <-ここがindex.html
protocol: 'file:',
slashes: true
}))
//mainWindow.webContents.openDevTools()
mainWindow.on('closed', function () {
mainWindow = null;
})
}

あとはapp.onで先に作った関数をいろいろ動くようにする。


index.js

app.on('ready', createPyProc)

app.on('ready', createWindow)

app.on('will-quit', exitPyProc)

app.on('window-all-closed', function () {
if (process.platform !== 'darwin') {
app.quit()
}
})

app.on('activate', function () {
if (mainWindow === null) {
createWindow()
}
})



index.html front-end部分

特に説明なし。vueで書かれている。というくらい。正直よくわかってないのが、bodyの外にscriptタグを。しかもrequire関数を使っているだけ。この記述が正しいのかはよく分かっていない。


index.html

<!DOCTYPE html>

<html>
<head>
<meta charset="UTF-8">
<title>Get HTTP Request</title>
<meta name="copyright" content="(c) 2018 bluelief.">
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<link rel="stylesheet" type="text/css" href="css/main.css">
</head>
<body>
<div id="result">
<input v-model="forminput" placeholder="edit me" v-on:keyup.13="submit"></input>
<br>{{message}}</div>
</body>
<script>
require('./http_req.js')
</script>
</html>


http_req 情報取得部分のjavascript

これのmethods部分だろうか。htmlで記述した<input v-model="forminput" placeholder="edit me" v-on:keyup.13="submit"></input>のsubmitに反応して発火。ボタンとか作らずEnter押して上げると反応します。

あとはaxios.get(request_url)で指定urlにアクセスします。これがpython serverにアクセスする部分です。


http_req.js

let app = new Vue({

el: '#result',
data: {
forminput: '',
message: 'Hello Vue!',
url: 'http://localhost:8080/'
},
methods: {
submit: () => {
request_url = app.url + app.forminput
axios.get(request_url)
.then((res) => {
app.message = res.data
})
.catch((res) => {
console.error(res)
})
}
}
})


python server

アクセスするurlに応じて情報を取得する感じです。特別なことはあまりしていないサンプル程度のbottleサーバー。


main.py

from bottle import route, run, template

import sys, urllib.request, urllib.error

@route("/<domain_name>")
def http_header(domain_name):
""" http header check """
host = "http://" + domain_name

try:
fd = urllib.request.urlopen(host)
except urllib.error.URLError as e:
return "[*] Accsess Error, %s" % e

result = '''
Request:
%s\n
--------- Header ----------
\n
'''
% fd.geturl()

for key, value in fd.info().items():
result += "%s = %s\n\n" % (key, value)

return result

run(host='localhost', port=8080, debug=True, reloader=True)



完成されたもの


最後に


  • Electronをやるならモチベーション維持のため、my cssを持っておくとイカしたGUIになって楽しいと思う。

  • デザインが得意でcssとかjavascript触れる友達を見つけよう。gitが触れればなおよし。

  • やはりElectronを採用するならjavascriptのスペシャリストを目指すべき。多分はやい。多分。

  • Electronで社内ツール作成の記事とかもチラっと見たけどwebアクセス + αというところに可能性は無限大だと思った。


javascript素人の所感


  • アロー関数、はて、イカ関数? => => =>

  • import? require?どっちやねん・・・

  • var const let???

  • どこからnodejsでどこまでjavascriptなんだ

  • dependencies、 devdependencies。細かすぎる
    ※指定次第でelectron-packageが動かない


参考文献

https://github.com/fyears/electron-python-example

Pythonでデスクトップアプリを作る with Electron - Qiita

bottle×Electronで簡単!PythonのGUIアプリ開発 - Qiita

https://jp.vuejs.org/index.html

https://www.npmjs.com/package/electron