EEL中 python端的函数名是如何传递给js端的

python端的函数名是如何传递给js端的

核心步骤:将函数名列表注入到动态生成的 eel.js 中,这样前端一开始引用的eel.js本身已经包含有py_function的函数名列表了。你打开开发者工具看看浏览器中的 eel.js文件源代码就知道了。

具体实现:

# 读取eel.js源文件,把代码放入_eel_js这个变量中
mimetypes.add_type('application/javascript', '.js')
_eel_js_file: str = pkg.resource_filename('eel', 'eel.js')
_eel_js: str = open(_eel_js_file, encoding='utf-8').read()
# Bottle Routesdef _eel() -> str:# 设置窗口大小start_geometry = {'default': {'size': _start_args['size'],'position': _start_args['position']},'pages':   _start_args['geometry']}# 把py函数名注入eel.js的源码中(改写eel.js的源码)page = _eel_js.replace('/** _py_functions **/','_py_functions: %s,' % list(_exposed_functions.keys()))page = page.replace('/** _start_geometry **/','_start_geometry: %s,' % _safe_json(start_geometry))btl.response.content_type = 'application/javascript'    # 由Bottle服务器对外提供/eel.js供访问_set_response_headers(btl.response)return page

JS端的函数名是如何传递给python端的

 核心步骤:python端扫描/读取eel.init(path)中的path整个目录(含子目录)的所有.js和.html文件,通过正则表达式匹配 eel.expose(xxxx),来获得暴露的函数名,然后创建同名的python函数。

你甚至可以专门建一个目录,这个目录只存放一个文本文件,把所有暴露的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); 

具体来说,eel.init(path)是通过遍历path文件夹及其子目录的全部指定扩展名的文件,并通过语法解析器 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

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

JS端函数是怎样被Python调用的

关键步骤:

1、eel.expose(js_function_name) 把函数名收集起来存放在_exposed_functions这个对象中

2、websocket收到message的时候,检查调用的函数名是否在_exposed_functions中,是则调用_exposed_functions中对应的函数。

既然可以用一个专门的目录,只存放一个文本文件,把所有暴露的js函数名以eel.expose(js_function_name) 的形式记录到一个文件中让python端扫描就可以完成函数名在python的注册,是不是就可以在前端删除掉eel.expose(js_function_name)这行呢?

当然不行,这行在前端还有一个作用,就是向websocket注册js函数,让websocket可以调用这些函数。可能是为了避免websocket操作权限过大,EEL限定它仅能调用eel.expose声明过的函数。规则就是把这些函数名存放在 _exposed_functions 这个对象中。websocket收到python端的调用js函数指令时,先看看函数名是否在_exposed_functions这个对象里面,在才调用,不在就跳过。

// 暴露的函数存放到_exposed_functions这个对象中

// 暴露的函数存放到_exposed_functions这个对象中expose: function(f, name) {if(name === undefined){name = f.toString();let i = 'function '.length, j = name.indexOf('(');name = name.substring(i, j).trim();}eel._exposed_functions[name] = f;},

 //  if(message.name in eel._exposed_functions) 才执行

//  if(message.name in eel._exposed_functions) 才执行eel._websocket.onmessage = function (e) {let message = JSON.parse(e.data);if(message.hasOwnProperty('call') ) {// Python making a function call into usif(message.name in eel._exposed_functions) {try {let return_val = eel._exposed_functions[message.name](...message.args);eel._websocket.send(eel._toJSON({'return': message.call, 'status':'ok', 'value': return_val}));} catch(err) {debuggereel._websocket.send(eel._toJSON({'return': message.call,'status':'error','error': err.message,'stack': err.stack}));}}} else if(message.hasOwnProperty('return')) {// Python returning a value to usif(message['return'] in eel._call_return_callbacks) {if(message['status']==='ok'){eel._call_return_callbacks[message['return']].resolve(message.value);}else if(message['status']==='error' &&  eel._call_return_callbacks[message['return']].reject) {eel._call_return_callbacks[message['return']].reject(message['error']);}}} else {throw 'Invalid message ' + message;}};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/327834.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

启明智显分享|国产RISC-V@480MHz“邮票孔”工业级HMI核心板,高品质低成本,仅34.9元!

「Model系列」芯片是启明智显针对工业、行业以及车载产品市场推出的系列HMI芯片,主要应用于工业自动化、智能终端HMI、车载仪表盘、串口屏、智能中控、智能家居、充电桩显示屏、储能显示屏、工业触摸屏等领域。此系列具有高性能、低成本的特点,支持工业宽…

Transformers实战01-开箱即用的 pipelines

文章目录 简介安装pipelines图片转文本文本生成情感分析零训练样本分类遮盖词填充命名实体识别自动问答自动摘要 pipeline 背后做了什么?使用分词器进行预处理将预处理好的输入送入模型对模型输出进行后处理 简介 Transformers 是由 Hugging Face 开发的一个 NLP 包…

读人工智能时代与人类未来笔记03_演变

1. 演变 1.1. 每个社会都找到了属于自己的一套适应世界的方法 1.1.1. 适应的核心,是有关人类心智与现实之间关系的概念 1.1.2. 人类认识周围环境的能力 1.1.2.1. 这种能力通过知识获得,同时也受到知识…

奥维地图下载高清影像的两种方式!以及ArcGIS、QGIS、GlobalMapper、自编工具下载高清影像的方法推荐!

今天来介绍一下奥维互动地图是如何下载高清影像的,也不是多了不起的功能!有朋友问,加上这个软件确实用的人多。 下载的高清数据在ArcGIS中打开的效果! 开始介绍奥维之前我们也介绍一下我们之前介绍的几个方法,没有优劣…

【提示学习论文】TCP:Textual-based Class-aware Prompt tuning for Visual-Language Model

TCP:Textual-based Class-aware Prompt tuning for Visual-Language Model(CVPR2024) 基于文本的类感知提示调优的VLMKgCoOp为baseline,进行改进,把 w c l i p w_{clip} wclip​进行投影,然后与Learnable prompts进行…

您可以使用WordPress创建的19种网站类型

当人们决定为什么他们应该使用WordPress时,我们经常会被问到“WordPress可以做[空白]吗?答案大多是肯定的。在本文中,我们将向您展示您可以使用WordPress创建的19种不同类型的网站,而无需学习任何编程技巧。 目录 隐藏 1 开始使用…

html--地图

<!DOCTYPE html> <html lang"en"> <head><meta charset"utf-8"><title>ECharts</title><!--Step:1 引入一个模块加载器&#xff0c;如esl.js或者require.js--><script src"js/esl.js"></scr…

SpringBoot项目的项目部署全过程

一、前端 安装nginx 1.将提前准备好的nginx的安装包上传到Linux中/opt目录下(我用的是Xftp) 2.解压 2.1:在xshell中解压该文件: tar -zxvf nginx-1.20.1.tar.gz 2.2:进入解压后的目录 cd nginx-1.20.1/ 2.3:安装需要的依赖 yum -y install zlib zlib-devel openssl openssl-de…

【Doris的安装与部署】

1 集群规划和环境准备 Doris作为一款MPP架构的OLAP数据库&#xff0c;可以在绝大多数主流的商用服务器上运行。 1.1 环境要求 一般推荐使用Linux系统&#xff0c;版本要求是CentOS 7.1及以上或者Ubuntu 16.04及以上&#xff0c;这也是目前服务器市场最主流的操作系统。 操作…

在 CSS 中使用 text-emphasis 来增强文本的趣味性

在CSS中设置文本样式的方法有很多。您可以更改颜色、大小、字体&#xff0c;甚至添加阴影和轮廓等效果。但最近&#xff0c;我了解到一个我以前没有听说过的时尚 CSS 属性&#xff0c;它非常棒&#xff01; 它被称为文本强调&#xff08;text-emphasis&#xff09;&#xff0c…

1725 ssm资产管理系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 java ssm资产管理系统是一套完善的web设计系统&#xff08;系统采用SSM框架进行设计开发&#xff0c;springspringMVCmybatis&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/…

基于STM32F401RET6智能锁项目(BS82166A_3触摸按键)

一、BS81x 特征 • 工作电压&#xff1a;2.2V~5.5V • 低待机电流 • 自动校准功能 • 可靠的触摸按键检测 • 自动切换待机 / 工作模式 • 最长按键输出时间检测 • 具备抗电压波动功能 • Level Hold&#xff0c;可选高有效或低有效 • NMOS 输出内建上拉电阻 /CMOS 直接 输出…

TypeScript学习日志-第二十三天(装饰器Decorator)

装饰器Decorator 一、类装饰器 ClassDecorator 其中返回的 target 是 Http 的构造函数&#xff0c;有了构造函数就不会去破坏其自身原有的结构&#xff0c;当我们 Http 里面有多个属性或者方法的&#xff0c;当是我们不想看或者改变它&#xff0c;这时候可以在构造函数中增加即…

【C++】每日一题 17 电话号码的字母组合

给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 可以使用回溯法来解决这个问题。首先定义一个映射关系将数字与字母对应起来…

数学建模——线性回归模型

目录 1.线性回归模型的具体步骤和要点&#xff1a; 1.收集数据&#xff1a; 2.探索性数据分析&#xff1a; 3.选择模型&#xff1a; 4.拟合模型&#xff1a; 5.评估模型&#xff1a; 1.R平方&#xff08;R-squared&#xff09;&#xff1a; 2.调整R平方&#xff08;Ad…

2024CCPC全国邀请赛(郑州)暨河南省赛

2024CCPC全国邀请赛&#xff08;郑州站&#xff09;暨河南省赛 一铜一银&#xff0c;虽不是线下第一次参赛但是第一次拿xcpc奖牌&#xff0c;还有个国赛奖真是不戳。感谢学长&#xff0c;感谢队友&#xff01; 虽然遗憾没有冲到省赛金&#xff0c;不过还有icpc商丘&#xff08…

Golang RPC实现-day01

导航 Golang RPC实现一、主体逻辑设计二、服务设计1、监听和接收请求2、处理请求(1)服务结构体定义(2)确认请求方和服务方编解码格式(3)循环读取请求(4)解析请求的内容(5)响应请求 三、读取和发送数据到连接中代码 Golang RPC实现 先来一个最简单的版本&#xff0c;后续更新。…

蜜蜂收卡系统 加油卡充值卡礼品卡自定义回收系统源码 前后端开源uniapp可打包app

本文来自&#xff1a;蜜蜂收卡系统 加油卡充值卡礼品卡自定义回收系统源码 前后端开源uniapp可打包app - 源码1688 卡券绿色循环计划—— 一项旨在构建卡券价值再利用生态的社会责任感项目。在当前数字化消费日益普及的背景下&#xff0c;大量礼品卡、优惠券因各种原因未能有效…

基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (三)

基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;三&#xff09; 大家继续看 https://lilianweng.github.io/posts/2023-06-23-agent/的文档内容 第二部分&#xff1a;内存 记忆的类型 记忆可以定义为用于获取、存储、保留以及随后检索信息的过程。人脑中有多…