JavaScript和Python打造跨平臺(tái)客戶端應(yīng)用——vue-pywebview-pyinstaller


前言

現(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)境

注意:在 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
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市挎狸,隨后出現(xiàn)的幾起案子扣汪,更是在濱河造成了極大的恐慌,老刑警劉巖锨匆,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件崭别,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡恐锣,警方通過查閱死者的電腦和手機(jī)茅主,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來土榴,“玉大人暗膜,你說我怎么就攤上這事”揆茫” “怎么了学搜?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)论衍。 經(jīng)常有香客問我瑞佩,道長(zhǎng),這世上最難降的妖魔是什么坯台? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任国撵,我火速辦了婚禮借尿,結(jié)果婚禮上碴裙,老公的妹妹穿的比我還像新娘沮趣。我一直安慰自己,他們只是感情好咪啡,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布首启。 她就那樣靜靜地躺著,像睡著了一般撤摸。 火紅的嫁衣襯著肌膚如雪毅桃。 梳的紋絲不亂的頭發(fā)上褒纲,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音钥飞,去河邊找鬼莺掠。 笑死,一個(gè)胖子當(dāng)著我的面吹牛读宙,可吹牛的內(nèi)容都是我干的彻秆。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼结闸,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼唇兑!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起膀估,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎耻讽,沒想到半個(gè)月后察纯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡针肥,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年饼记,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片慰枕。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡具则,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出具帮,到底是詐尸還是另有隱情博肋,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布蜂厅,位于F島的核電站匪凡,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏掘猿。R本人自食惡果不足惜病游,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望稠通。 院中可真熱鬧衬衬,春花似錦、人聲如沸改橘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽飞主。三九已至兼砖,卻和暖如春奸远,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背讽挟。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工懒叛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人耽梅。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓薛窥,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親眼姐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子诅迷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容