python GUI庫 EEL + VUE.js 開發環境配置 聯調

?eel開發環境啟動的服務器默認端口是8000,如果前端界面的開發也是直接在EEL開發環境中進行,一切好辦。但如果前端用vue,則需要另外啟動專用的vue開發環境的服務器(Vue CLI (npm run serve)默認端口是8080,Vite (npm run dev)默認端口是5173)。

?那怎么同步聯調開發呢?

核心操作有兩點:

1、python代碼中的eel.start() 參數配置指定啟動頁為vue環境的入口頁

2、vue頁面中引入eel.js的時候,引用路徑為eel環境的eel.js , 以及把websocket的host設為eel環境的host。

# main.pyimport eel@eel.expose
def say_hello_py(x):print("Hello from %s" % x)"""開發環境:
1、python開發環境的eel.start()參數:設置啟動頁面為vue開發環境的服務端口5173,
2、vue開發環境中的public/index.html里引用eel.js時,路徑是引用python eel環境的eel.js
3、vue開發環境中的public/index.html里設置websocket的服務器為python eel所啟動的那個服務器。生產環境:
和正常的一樣使用
"""
def start_eel(environment):"""判斷當前是開發環境還是生產環境,選擇不同的eel.start()參數配置"""if environment == 'develop':    # 開發環境directory = 'src'           # 注意!這個值對應的是EEL服務器的文件夾,不是VUE服務器的文件夾app ='chrome'start_page = {'port': 5173}       # 指向:http://localhost:5173/eel_kwargs = dict(          # 設置  http://localhost:9000 為eel服務器mode=app,host="localhost",port=9000,)else:                           # 生產環境directory = 'web'app = 'chrome'start_page = 'index.html'eel_kwargs = dict(mode=app,port=0,size=(1280, 800),)eel.init(directory)eel.start(start_page, **eel_kwargs)if __name__ == "__main__":print("啟動python...")start_eel('develop')

// vue 的 public/index.html<%if(process.env.NODE_ENV === 'production'){ %>
<script type="text/javascript" src="/eel.js"></script>
<%}else{%>
<script type=text/javascript src="http://localhost:9000/eel.js"></script>
<script>window.eel.set_host("ws://localhost:9000");
</script>
<%}%>

<!-- vue 中 public/index.html--><!DOCTYPE html>
<html><head><title>Hello, World!</title><script type=text/javascript src="http://localhost:9000/eel.js"></script>
<script>window.eel.set_host("ws://localhost:9000");
</script><script type="text/javascript">eel.expose(say_hello_js); // Expose this function to Pythonfunction say_hello_js(x) {const msg = "Hello from " + xdocument.getElementById("msgbox").innerHTML=msg;}eel.say_hello_py("Javascript World!"); // Call a Python function</script></head><body>Hello, World!<button onclick="eel.say_hello_py('Javascript Button!')">調用Python函數</button><p id="msgbox"></p><button onclick="say_hello_js('Javascript Button!')">調用JS函數</button></body>
</html>

==========

踩坑小記:

    eel.init(directory)

當使用5173端口作前端服務時,?eel.init(directory)? 的directory 這個配置項對應的文件夾應該是VUE開發環境的本地文件夾。如果VUE開發環境不在本機上,你可以在本地構建一個文件夾,把需要用到的js函數的函數名放入這個文件夾中即可。

我一開始沒有留意,結果是界面可以成功啟動,界面啟動過程沒有報錯,網頁端調用python函數也成功,但python端調用js函數就報錯提示:[AttributeError: module 'eel' has no attribute 'say_hello_js'] ,把eel.init(directory)的directory配置為vue服務的本地目錄就成功了。

甚至你可以專門建一個目錄,這個目錄只存放一個文本文件,把所有暴露的js函數名以eel.expose(js_function_name) 的形式記錄到一個文件中,并以.js為擴展名命名,也可以。

//expose_js_function_name.jseel.expose(say_hello_js); 
eel.expose(my_js_function_1); 
eel.expose(my_js_function_2); 
eel.expose(my_js_function_3); 
eel.expose(my_js_function_4); 

跟蹤了一下源代碼,發現確實是通過遍歷該文件夾及其子目錄的全部指定擴展名的文件,并通過語法解析器 EXPOSED_JS_FUNCTIONS (基于PyParsing構建)進行匹配。

EXPOSED_JS_FUNCTIONS的解釋規則是:用正則表達式匹配,解析得到函數名,這些函數名被存儲在js_functions這個集合中。

得到這些js函數名后,通過_mock_js_function() 構建同名函數,構建的這個函數對于eel這個類來說是全局函數,所以對于main.py來說,就是【eel.同名函數】,就可以通過eel.js_function_name() 調用了。

# 如果程序未被PyInstaller打包成exe,則返回path的絕對路徑,否則exe創建的臨時資源目錄_MEIPASS
def _get_real_path(path: str) -> str:if getattr(sys, 'frozen', False):return os.path.join(sys._MEIPASS, path) # type: ignore # sys._MEIPASS is dynamically added by PyInstallerelse:return os.path.abspath(path)'''
當你使用 PyInstaller 將腳本+資源打包成一個exe后。運行exe時,會動態創建一個臨時目錄(通常是在系統的臨時文件夾中),并將可執行文件內部的所有資源解壓到這個臨時目錄。sys._MEIPASS 就是這個臨時目錄的路徑。
'''
def init(path: str, allowed_extensions: List[str] = ['.js', '.html', '.txt', '.htm','.xhtml', '.vue'], js_result_timeout: int = 10000) -> None:global root_path, _js_functions, _js_result_timeoutroot_path = _get_real_path(path)js_functions = set()for root, _, files in os.walk(root_path):    # 遍歷它的子目錄for name in files:if not any(name.endswith(ext) for ext in allowed_extensions):continuetry:with open(os.path.join(root, name), encoding='utf-8') as file:contents = file.read()expose_calls = set()matches = EXPOSED_JS_FUNCTIONS.parseString(contents).asList() # 對文件進行解釋,把【暴露給python的js函數】匹配出來。for expose_call in matches:# Verify that function name is validmsg = "eel.expose() call contains '(' or '='"assert rgx.findall(r'[\(=]', expose_call) == [], msgexpose_calls.add(expose_call)        # 收集此文件的暴露函數js_functions.update(expose_calls)        # 收集全部文件的暴露函數except UnicodeDecodeError:pass    # Malformed file probably_js_functions = list(js_functions)for js_function in _js_functions:_mock_js_function(js_function)        # 將找到的JS函數名稱保存起來,并準備在 websocket 連接時使用_js_result_timeout = js_result_timeout

===============================================

對于eel.start() 參數配置中的start_page參數。

根據作者官方github上的資料,eel.start()的第一個參數是啟動頁的html文件名(入口頁面),是字符串。為什么可以接收一個dict變量{'port':5173}呢?

追蹤了一下源代碼,發現其值為dict類型時,可以支持的參數包含了協議scheme 、域host 、端口port 、路徑path 這幾個參數

其值為字符串時,字符串應該為base_url?之后的訪問路徑。

代碼追蹤:def start(*start_urls: str, **kwargs: Any)? -->? show(*start_urls) -->brw.open(list(start_urls), _start_args) -->?open(start_pages: Iterable[Union[str, Dict[str, str]]], options: OptionsDictT) -->?_build_urls(start_pages: Iterable[Union[str, Dict[str, str]]], options: OptionsDictT) -->_build_url_from_dict(page, options)

def _build_url_from_dict(page: Dict[str, str], options: OptionsDictT) -> str:scheme = page.get('scheme', 'http')host = page.get('host', 'localhost')port = page.get('port', options["port"])path = page.get('path', '')if not isinstance(port, (int, str)):raise TypeError("'port' option must be an integer")return '%s://%s:%d/%s' % (scheme, host, int(port), path)def _build_url_from_string(page: str, options: OptionsDictT) -> str:if not isinstance(options['port'], (int, str)):raise TypeError("'port' option must be an integer")base_url = 'http://%s:%d/' % (options['host'], int(options['port']))return base_url + page

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/11969.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/11969.shtml
英文地址,請注明出處:http://en.pswp.cn/web/11969.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

CentOS7中如何docker-compose

在 CentOS 7 上安裝 docker-compose 需要幾個步驟 步驟 1: 安裝 Docker 首先&#xff0c;確保你已經安裝了 Docker。如果沒有安裝&#xff0c;可以通過以下命令安裝&#xff1a; sudo yum update -y sudo yum install -y yum-utils sudo yum-config-manager --add-repo http…

攻防世界(CTF)~web-supersqli(詳細解題思路)

題目介紹 題目描述“隨便注” 先看一下是否存在注入 判斷閉合方式 輸入1’ and 11-- -正常回顯 輸入1and 12-- -無回顯,確認是單引號閉合 看一下列數 輸入1 order by 2-- - 有回顯 輸入1 order by 3-- - 報錯&#xff0c;由此判斷兩列 使用union聯合注入發現select被過濾了&a…

WMS倉儲管理系統如何讓倉庫管理有過程

在當今競爭激烈的商業環境中&#xff0c;WMS倉儲管理系統的智能化與過程化管理顯得尤為重要。一個具有過程管理的WMS倉儲管理系統不僅能夠幫助企業實時監控、分析和調度倉庫作業&#xff0c;還能顯著提升作業效率和成本控制能力。下面&#xff0c;我們就來深入探討一下這種“有…

流媒體zlmediakit

目標&#xff1a; 流媒體部署 內容&#xff1a; 使用開源流媒體zlmediakit docker搭建&#xff1a; docker run -d -p 10000:10000 -p 10000:10000/udp -p 1935:1935 -p 8080:80 -p 8554:554 -p 8443:443 -p 8000:8000/udp -p 9000:9000/udp -p 30000-30050:30000-30050…

IT Tools

vs & vscode工具 Vs Extensions & Remote Development Vs Extensions Remote-SSH VSCode遠程連接到Linux并實現免密碼登錄 Git Graph C cppreference.com cplusplus 鏡像站點 用于下載 QT, Ubuntu, 清華鏡像站點 CMake Download Documents Cmake 構建QT …

IO系列(三) - 文件讀寫操作介紹

一、摘要 在之前的文章中&#xff0c;我們了解到在 Java I/O 體系中&#xff0c;File 類是唯一代表磁盤文件本身的對象。 File 類定義了一些與平臺無關的方法來操作文件&#xff0c;包括檢查一個文件是否存在、創建、刪除文件、重命名文件、判斷文件的讀寫權限是否存在、設置…

撳針在醫保上叫什么?

點擊文末領取撳針的視頻教程跟直播講解 創新型皮內針&#xff08;撳針&#xff09;——醫保甲類產品 皮內針&#xff08;撳針&#xff09;技術屬于重點推廣的中醫適宜技術&#xff0c;是將特制的小型針具固定于腧穴部位的皮內或皮下做較長時間留針的一種方法&#xff0c;稱“…

2024年 C++音視頻開發學習路線(ffmpeg/rtsp/srs/webrtc/hls)

在音視頻工作領域&#xff0c;很多人可能會陷入徘徊和迷茫的境地。音視頻的知識紛繁復雜&#xff0c;自己學習非常困難&#xff0c;既需要非常扎實的基礎知識&#xff0c;又需要有很多的工程經驗&#xff1b;不知道如何學&#xff0c;怎樣才能查漏補缺自己的技術短板。 對于音…

QT C++ widget layout 嵌套 例子2

在上篇文章中描述了實中套虛&#xff08;用setLayout&#xff09;&#xff0c;虛中套實&#xff08;用addWidget&#xff09;。 本文再加1條&#xff0c;虛中套虛&#xff08;用addLayout&#xff09;。 所謂虛中套虛&#xff0c;是layout 套 layout 。 另外用循環代碼生成從…

記錄接口請求偶發504 Gateway Time-out問題

項目場景&#xff1a; 我們將服務部署到A公司服務器中&#xff0c;使用了共五臺服務器&#xff0c;分別是&#xff1a;1.NG服務器 2.日志服務器 3.緩存服務器 4.應用服務器1 5.應用服務器2 。而請求過來首先到達的是他們的物理代理服務器&#xff0c;然后再轉發請求到我們的ng…

【Neo4jJDK開箱即用的安裝全流程】

neo4j:命令行本地訪問loclhost neo4j:命令行本地訪問loclhost2 neo4j操作 Neo4j桌面版數據庫導出導入 Neo4j安裝與配置以及JDK安裝與配置教程&#xff08;超詳細&#xff09; Neo4j 安裝、使用教程 Neo4j安裝教程 Neo4J桌面版的配置和連接Pycharm jdk-neo對應版本 JDK ORACLE中…

數據結構(四)————二叉樹和堆(中)

制作不易&#xff0c;三連支持一下唄&#xff01;&#xff01;&#xff01; 文章目錄 前言一、堆的概念及結構二、堆的實現三.堆的應用 總結 前言 CSDN 這篇博客介紹了二叉樹中的基本概念和存儲結構&#xff0c;接下來我們將運用這些結構來實現二叉樹 一、堆的概念及結構 1…

招聘公司要求跳槽時間間隔不能太短,我的簡歷不符合要求,怎么辦?

很多招聘公司要求就很奇葩,什么三五原則,什么二一原則,意思就是,你幾年內,不能在超過幾家公司內任職。你就說多奇葩啊,他們都不能保證自己的員工在自己公司干多久,甚至裁掉剛干了半年的員工,也是他們干出來的事,然后他們還好意思有這種奇葩要求。 目錄 1 虛假的雙向選…

OpenPCDet算法的網絡結構及工作原理

OpenPCDet是一個用于三維點云目標檢測的開源算法庫。它提供了完整的目標檢測流程&#xff0c;包括數據預處理、網絡模型、損失函數、后處理等。OpenPCDet基于PyTorch框架實現&#xff0c;并針對點云數據進行了深度優化&#xff0c;以實現高效的目標檢測和定位。 OpenPCDet的目…

SpringMVC 注解詳解

SpringMVC 注解詳解 1. 引言 SpringMVC 是 Spring 框架中的 Web 層解決方案&#xff0c;它通過注解的方式來簡化 MVC 模式的實現。本篇將詳細介紹 SpringMVC 中常用的注解及其用法。 2. SpringMVC 注解分類 SpringMVC 的注解主要分為以下幾類&#xff1a; 2.1 核心注解 C…

用sunoAI寫粵語歌的方法,博主已經親自實踐可行

粵語歌還是很好聽的&#xff0c;那么如何使用suno進行粵語歌的創作呢&#xff1f; 本文和大家進行分享下如何進行粵語歌曲的創作。 訪問地址如下&#xff08;電腦端/手機端一個地址&#xff09;&#xff1a; ?https://suno3.cn/#/?i8NCBS8_WXTT 在微信瀏覽器中也可以直接…

css 案例 橫向滾動漸變

效果 完整代碼&#xff1a; <template><view class"content"><view class"tab"><view class"tab-item" v-for"(item,index) in tab" :key"index" click"handlerTab(index)":class"ind…

winserver系統設置圖片查看器

新建 .bat 批處理執行文件&#xff0c;內容如下&#xff1a; echo off&cd&color 0a&cls echo Set Win10 Photo Viewer reg add "HKLM\SOFTWARE\Microsoft\Windows Photo Viewer\Capabilities\FileAssociations" /v ".jpg" /t REG_SZ /d Photo…

MySQL——利用變量進行查詢操作

新建鏈接&#xff0c;自帶world數據庫&#xff0c;里面自帶city表格。 DQL # MySQL利用變量進行查詢操作 set cityNameHaarlemmermeer; select * from city where NamecityName;# 多個結果查詢 set cityName1Haarlemmermeer; set cityName2Breda; set cityName3Willemstad; s…

Mysql--期末復習

目錄 一.變量 1.系統變量 global session 2.用戶自定義變量 3.局部變量 二.觸發器 1.pysx函數(銷售)拼音縮寫觸發器 2.goods維護(存儲過程) 3.xkglxt 4.訂單延期 一.變量 1.系統變量 global session 2.用戶自定義變量 1.不用提前聲明&#xff0c;使用時直接 變量…