两年没写博客了,这两年自己主导设计和开发了不少项目,收获颇丰,以后的博客中我会逐一介绍(不限于玩转python系列)。
我为什么要做图形界面?
假设你在负责一个项目,如果你的用户和我们一样是技术人员,显然应该留给用户更多的选择,使自己的产品尽可能灵活。直白一点就是:我提供足够的功能就行,怎么用是你的事。
某种意义上说,这其实是把责任抛给了用户(这里没有贬低的意思)。但当你的用户是技术小白,这样做是不行了,此时需要遵循的原则是,尽量屏蔽技术细节,用俗语代替术语,尽可能使用图形界面。最后一点尤为重要,命令行对于非技术人员是极不友好的。
我选择了何种技术?
HTML + bootstrap-vue + gevent-websocket+bottle
选择这个技术组合是受到了Electron的启发,但是我的后端涉及深度学习框架,与其用nodejs+python不如全盘python。使用websocket的原因也很简单,很多深度学习任务耗时很长,为了更好的客户体验,我们需要把原先输出在控制台的信息反馈到前端页面上,无论是单次http请求还是用ajax轮询都是不现实的。
简单的例子
目录结构:
|- app.py
bottle.py
view
|-index.html
下面的这段代码会启动一个http-server和一个socket-server,并打开浏览器页面。
"""app.py: Start a http-server and a socket-server."""
import os
import sys
import time
import webbrowser
from threading import Thread
from bottle import Bottle, static_file
host = '127.0.0.1'
port = 8080
app = Bottle()
def open_browser():
from urllib import request
while True:
try:
request.urlopen(f'http://{host}:{port}/check')
webbrowser.open(f'http://{host}:{port}/view/index.html')
return
except Exception as e:
time.sleep(2)
def start_websocket_server():
from gevent.pywsgi import WSGIServer
from geventwebsocket.handler import WebSocketHandler
server = WSGIServer((host, port+1),
YOUR_APP, # replace it with your own app
handler_class=WebSocketHandler)
server.serve_forever()
@app.route('/check')
def check_status():
return {
'result': 'success',
'data': None,
'message': 'app is running'
}
@app.route('/view/<file_name>')
def view(file_name):
view_path = os.path.join(
os.path.dirname(
os.path.abspath(__file__)
),
'view'
)
return static_file(file_name, root=view_path)
Thread(target=open_browser).start()
Thread(target=start_websocket_server).start()
app.run(host=host, port=port, debug=True)
其他选择:
如果真的想做功能复杂的图形化界面,我还是建议入手pyqt或者pyside,与他们相比,html+js的组合还是有些“粗糙”。