前言
現(xiàn)如今屯曹,要說比較火的編程語言當(dāng)屬 JavaScript 和 Python 了,這兩門語言都可以獨(dú)立編寫前端頁面惊畏、后端服務(wù)器恶耽、手機(jī) APP、電腦客戶端等等颜启,無所不能偷俭。不過,不同的編程語言有不同的側(cè)重點(diǎn)农曲。比如 JavaScript 寫網(wǎng)頁得心應(yīng)手,Python 處理大數(shù)據(jù)信手拈來驻债。那么乳规,能不能取兩者的優(yōu)點(diǎn),構(gòu)建一個(gè)跨平臺(tái)客戶端框架呢合呐?這就有了今天的主角:vue-pywebview-pyinstaller暮的。
應(yīng)用簡(jiǎn)介
vue-pywebview-pyinstaller 是一款基于 Vue3、pywebview 和 PyInstaller 框架淌实,構(gòu)建 macOS 和 windows 平臺(tái)客戶端的應(yīng)用冻辩。本應(yīng)用的視圖層采用 HTML+JS+CSS猖腕,業(yè)務(wù)層采用本地 Python『奚粒考慮到某些生物計(jì)算場(chǎng)景數(shù)據(jù)量大倘感,數(shù)據(jù)私密,因此將數(shù)據(jù)上傳到服務(wù)器計(jì)算咙咽,并不一定是最優(yōu)解老玛,選擇采用本地 Python 也是一種不錯(cuò)的選擇。不過钧敞,如果需要調(diào)用遠(yuǎn)程 API蜡豹,本應(yīng)用也是支持的。
應(yīng)用優(yōu)勢(shì)
- 采用 Vue3 框架開發(fā)視圖層溉苛,簡(jiǎn)潔高效
- 采用 Python 編程語音開發(fā)業(yè)務(wù)層镜廉,模塊豐富
- 本應(yīng)用已經(jīng)封裝打包環(huán)節(jié),一鍵生成 macOS 和 windows 平臺(tái)的客戶端應(yīng)用愚战。開發(fā)者只需要關(guān)注試圖效果和業(yè)務(wù)邏輯本身娇唯,將繁重復(fù)雜的打包環(huán)節(jié)交給本應(yīng)用處理即可
適用場(chǎng)景
- 對(duì)軟件的用戶界面有一定美感要求
- 需要用到 Python 中的人工智能、生信分析等模塊
- 考慮搭建本地應(yīng)用凤巨,使用本機(jī)計(jì)算和存儲(chǔ)資源
適用人群
熟悉 Vue3 和 Python 編程的程序員视乐。
應(yīng)用安裝
運(yùn)行環(huán)境
- npm6.0+ (NodeJs 安裝教程)
- Python3.5-3.8 (Python 安裝教程)
注意:在 windows 系統(tǒng)下,由于 Pywebview3 所依賴的 pythonnet 包僅支持 Python3.5-3.8 版本敢茁,因此佑淀,推薦 win 用戶使用 Python3.8 版本。
應(yīng)用下載
利用 git(git 安裝教程) 下載應(yīng)用彰檬,如下所示:
git clone https://github.com/pangao1990/vue-pywebview-pyinstaller.git
或者伸刃,直接在我的 github 下載。
# 進(jìn)入項(xiàng)目
cd vue-pywebview-pyinstaller
進(jìn)入項(xiàng)目逢倍,項(xiàng)目清單如下所示:
[站外圖片上傳中...(image-4dfb64-1648107195346)]
初始化
下載完畢后捧颅,運(yùn)行初始化命令,程序會(huì)自動(dòng)下載安裝對(duì)應(yīng)操作平臺(tái)的所需依賴軟件较雕,如下所示:
# 初始化
npm run init
沒報(bào)錯(cuò)信息碉哑,則初始化完成,如下所示:
[站外圖片上傳中...(image-22ef4-1648107195346)]
[站外圖片上傳中...(image-b8186c-1648107195346)]
項(xiàng)目里多了一個(gè) node_modules 文件夾亮蒋,用于存放 npm 下載的包扣典;多了一個(gè) pyenv 文件夾,用于存放 Python 虛擬環(huán)境慎玖。
應(yīng)用運(yùn)行
輸入如下命令贮尖,即可啟動(dòng)應(yīng)用:
npm run start
終端顯示如下:
[站外圖片上傳中...(image-b94d4f-1648107195346)]
同時(shí),會(huì)啟動(dòng)一個(gè)客戶端程序趁怔,如下:
[站外圖片上傳中...(image-3b4318-1648107195346)]
整體效果如下所示(gif 圖片加載可能有點(diǎn)慢):
[站外圖片上傳中...(image-1170ab-1648107195346)]
高級(jí)用法
客戶端引擎介紹
本應(yīng)用基于 pywebview 構(gòu)建客戶端湿硝。而 pywebview 構(gòu)架構(gòu)建客戶端的原理是利用本地電腦自帶的瀏覽器引擎驅(qū)動(dòng)薪前,模擬生成客戶端。本質(zhì)上還是網(wǎng)頁关斜,或者說是一個(gè)瀏覽器示括,但是感官上和本地客戶端沒有差別。
那么蚤吹,基于 pywebview 構(gòu)架構(gòu)建客戶端的成敗或質(zhì)量例诀,就與本地電腦的瀏覽器引擎息息相關(guān)了。
windows 系統(tǒng)
在 windows 系統(tǒng)上裁着,大體上分為兩類客戶端引擎:正常模式和兼容模式繁涂。
- 正常模式
正常模式下,按照 edgechromium 二驰,edgehtml扔罪, mshtml 的客戶端引擎依次檢索。如果本地電腦 edge 瀏覽器支持這些引擎桶雀,則客戶端可以正常啟動(dòng)矿酵。否則,請(qǐng)安裝對(duì)應(yīng)的 EdgeWebView2Runtime 瀏覽器引擎矗积。
- 兼容模式
如果本地電腦 edge 瀏覽器不支持這些引擎全肮,同時(shí)也不想下載 EdgeWebView2Runtime ,那么就可以使用兼容模式棘捣。兼容模式的原理就是利用 CEFPython辜腺,嵌入 Chromium 的 Web 瀏覽器控件。也就是只要本地電腦安裝了谷歌瀏覽器 V66 版及其以上版本乍恐,即可正常啟動(dòng)客戶端评疗。缺點(diǎn)就是生成的安裝包體積會(huì)增加大約 60M 左右。
macOS 系統(tǒng)
macOS 系統(tǒng)的瀏覽器引擎就沒有那么多版本了茵烈,由于 macOS 系統(tǒng)的封閉性百匆,在 macOS 系統(tǒng)就只有一種 WebKit 引擎可用。
不過呜投,在 macOS 系統(tǒng)卻存在另一個(gè)問題加匈。那就是蘋果自主研發(fā)的 M1 芯片。由于 windows 系統(tǒng)隨處可見仑荐,我可以找很多電腦測(cè)試雕拼。mac 電腦我就只有一臺(tái) M1 芯片和一個(gè) x86_64 芯片,做不了更多測(cè)試释漆”唬總之篮迎,目前我這兩臺(tái)蘋果電腦構(gòu)建的客戶端不能交叉使用男图,原因不明示姿。
構(gòu)建客戶端 API
構(gòu)建客戶端的主程序是在 pyapp 文件夾下的 main.py 和 mainCEF.py ,如下所示:
[站外圖片上傳中...(image-f12ceb-1648107195346)]
mainCEF.py 腳本的內(nèi)容和 main.py 幾乎一模一樣逊笆,也就是 新增了一個(gè) cef 模式栈戳,用于 windows 系統(tǒng)的兼容模式。
[站外圖片上傳中...(image-5c9f93-1648107195346)]
main.py 里面主要是依靠 webview.create_window 和 webview.start 這兩個(gè) API 來構(gòu)建客戶端难裆。其他的一些 API子檀,我也會(huì)在后面的教程中詳細(xì)介紹∧烁辏或者可以直接查看 pywebview 官網(wǎng) 了解詳情褂痰。
webview.create_window
webview.create_window(title, url='', html='', js_api=None, width=800, height=600, \
x=None, y=None, resizable=True, fullscreen=False, \
min_size=(200, 100), hidden=False, frameless=False, \
minimized=False, on_top=False, confirm_close=False, \
background_color='#FFF')
創(chuàng)建一個(gè)新的 pywebview 窗口,并返回其實(shí)例症虑。在開始 GUI 循環(huán)之前缩歪,窗口不會(huì)顯示。
- title 窗口標(biāo)題
- url 要加載的 URL谍憔。如果 URL 沒有協(xié)議前綴匪蝙,則將其解析為相對(duì)于應(yīng)用程序入口點(diǎn)的路徑∠捌叮或者逛球,可以傳遞 WSGI 服務(wù)器對(duì)象來啟動(dòng)本地 Web 服務(wù)器。
- html 要加載的 HTML 代碼苫昌。如果同時(shí)指定了 URL 和 HTML颤绕,HTML 優(yōu)先。
- js_api 將 python 對(duì)象暴露到當(dāng)前 pywebview 窗口的 DOM 中蜡歹。js_api 對(duì)象的方法可以通過調(diào)用 window.pywebview.api.<methodname>(<parameters>)從 Javascript 執(zhí)行屋厘。請(qǐng)注意,調(diào)用 Javascript 函數(shù)會(huì)收到一個(gè)包含 python 函數(shù)的返回值月而。只有基本的 Python 對(duì)象(如 int汗洒、str、dict......)才能返回 Javascript父款。
- width 窗戶寬度溢谤。默認(rèn)值為 800px。
- height 窗戶高度憨攒。默認(rèn)值為 600px世杀。
- x 窗口 x 坐標(biāo)。默認(rèn)值居中肝集。
- y 窗口 y 坐標(biāo)瞻坝。默認(rèn)值居中。
- resizable 是否可以調(diào)整窗口大小杏瞻。默認(rèn)值為 True
- fullscreen 從全屏模式開始所刀。默認(rèn)為 False
- min_size 指定最小窗口大小的(寬度衙荐、高度)元組。默認(rèn)值為 200x100
- hidden 默認(rèn)情況下創(chuàng)建一個(gè)隱藏的窗口浮创。默認(rèn)為 False
- frameless 創(chuàng)建一個(gè)無框窗口忧吟。默認(rèn)值為 False。
- minimized 以最小化模式啟動(dòng)
- on_top 將窗口設(shè)置為始終位于其他窗口的頂部斩披。默認(rèn)值為 False溜族。
- confirm_close 是否顯示窗口關(guān)閉確認(rèn)對(duì)話框。默認(rèn)為 False
- background_color 加載 WebView 之前顯示的窗口的背景顏色垦沉。指定為十六進(jìn)制顏色煌抒。默認(rèn)值為白色。
- transparent 創(chuàng)建一個(gè)透明的窗口厕倍。Windows 不支持摧玫。默認(rèn)值為 False。請(qǐng)注意绑青,此設(shè)置不會(huì)隱藏或使窗口鉻透明诬像。將窗口 chrome setframeless 隱藏為 True。
webview.start
webview.start(func=None, args=None, localization={}, gui=None, debug=False, http_server=False)
啟動(dòng) GUI 循環(huán)并顯示之前創(chuàng)建的窗口闸婴。此函數(shù)必須從主線程調(diào)用坏挠。
- func 啟動(dòng) GUI 循環(huán)時(shí)調(diào)用的函數(shù)。
- args 函數(shù)參數(shù)邪乍〗岛荩可以是單個(gè)值,也可以是元組值庇楞。
- localization 帶有本地化字符串的詞典榜配。默認(rèn)字符串及其鍵在 localization.py 中定義
- gui 強(qiáng)制使用特定的 GUI。允許的值是 cef吕晌、qt 或 gtk蛋褥,具體取決于平臺(tái)。
- debug 啟用調(diào)試模式睛驳。
- http_server 啟用內(nèi)置 HTTP 服務(wù)器烙心。如果啟用,本地文件將使用隨機(jī)端口上的本地 HTTP 服務(wù)器提供服務(wù)乏沸。對(duì)于每個(gè)窗口淫茵,都會(huì)生成一個(gè)單獨(dú)的 HTTP 服務(wù)器。對(duì)于非本地 URL蹬跃,此選項(xiàng)將被忽略匙瘪。
域間通信
從 Python 調(diào)用 Javascript
window.evaluate_js(code, callback=None)允許您使用同步返回的最后一個(gè)值執(zhí)行任意 Javascript 代碼。如果提供了回調(diào)函數(shù),則解析 promise丹喻,并調(diào)用回調(diào)函數(shù)算灸,結(jié)果作為參數(shù)。Javascript 類型轉(zhuǎn)換為 Python 類型驻啤,例如 JS 對(duì)象到 Python 字典,數(shù)組到列表荐吵,未定義為 None骑冗。由于實(shí)現(xiàn)限制,字符串“null”將被計(jì)算為 None先煎。另外贼涩,evaluate_js 返回的值限制為 900 個(gè)字符內(nèi)。
從 Javascript 調(diào)用 Python
從 Javascript 調(diào)用 Python 函數(shù)可以通過兩種不同的方法完成薯蝎。
- 通過將 Python 類的實(shí)例暴露給 create_window 的 js_api遥倦。該類的所有可調(diào)用方法都將以 pywebview.api.method_name 的形式公開到 JS 域中。方法名稱不得以下劃線開頭占锯。
- 通過將函數(shù)傳遞給窗口對(duì)象的 expose(func)這將以 pywebview.api.func_name 的形式將一個(gè)或多個(gè)函數(shù)公開到 JS 域袒哥。與 JS API 不同,expose 也允許在運(yùn)行時(shí)公開函數(shù)消略。如果 JS API 和以這種方式公開的函數(shù)之間存在名稱沖突堡称,則后者優(yōu)先。
打包客戶端
pywebview 建議 macOS 用 py2app 打包艺演,windows 用 pyinstaller 打包却紧。但是我發(fā)現(xiàn) pyinstaller 也可以很順暢得打包 macOS 應(yīng)用,雖然移植有點(diǎn)問題胎撤。
我就不介紹 pyinstaller 的打包方法了晓殊,后面我會(huì)出這個(gè)框架詳細(xì)的打包介紹。這里我將打包方法封裝在應(yīng)用中伤提,只需要按命令打包即可巫俺。
# 預(yù)打包,帶console肿男,方便輸出日志信息
npm run pre
# 預(yù)打包识藤,帶console,兼容模式次伶,僅win系統(tǒng)
npm run pre:cef
# 預(yù)打包痴昧,帶console,生成文件夾冠王,僅win系統(tǒng)
npm run pre:folder
# 預(yù)打包赶撰,帶console,生成文件夾,兼容模式豪娜,僅win系統(tǒng)
npm run pre:folder:cef
# 正式打包
npm run build
# 正式打包餐胀,兼容模式,僅win系統(tǒng)
npm run build:cef
# 正式打包瘤载,生成文件夾否灾,僅win系統(tǒng)
npm run build:folder
# 正式打包,生成文件夾鸣奔,兼容模式墨技,僅win系統(tǒng)
npm run build:folder:cef