python的gui太难用了,唯一能配置独立前端的程序只有web。所以用web做前端,到python,完美!
环境准备
Python 3.9
Chrome浏览器(由于Eel是直接调用的Chrome的app启动模式,所以自己很轻量,不过需要提前安装有Chrome)
安装Eel库
pip install eel
文件结构
├── main.py 主入口
├── venv virtualenv环境
└── web 静态文件
├── css
├── favicon.ico
├── img
└── main.html
上面web文件夹用来存放各种静态文件,我是直接用的CDN上的css和js库,比用npm装到本地还省事儿。
这里主要提一下favicon.ico这个文件,以前撸html从来没做过这个图标,在Eel中这个文件将会显示为程序左上角的图标,所以还是挑个好看点的扔进来吧。
main.py
import eel # 定义html文件所在文件夹名称 eel.init('web') @eel.expose # 使用装饰器,类似flask里面对路由的定义 def py_fun(a): content = '你好!' + a return(content) # 测试调用js中的函数,同样需要使用回调函数 js_return = eel.js_fun('python传过去的参数')(lambda x: print(x)) # 启动的函数调用放在最后,port=0表示使用随机端口,size=(宽,高) eel.start('main.html', port=0, size=(600,300))
main.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Eel演示</title> <link href="https://cdn.bootcss.com/twitter-bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"> <script type="text/javascript" src="/eel.js"></script> </head> <body> <div class="container"> <div class="card mt-4"> <div class="card-body"> <h4>js & py互调测试</h4> <input type="text" class="form-control" id="in"> <p id="out"></p> <button class="btn btn-lg btn-success" onclick="doThis()">调用Python函数</button> </div> </div> </div> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <script src="https://cdn.bootcss.com/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script> <script> // 调用python中的函数,注意需要在定义前加上async声明异步 async function doThis(){ var par=$("#in").val(); let content = await eel.py_fun(par)(); //这里用let不用var,调用的python函数后面是两对括号 $("#out").text(content); } // 将js中的函数暴露给python,这个貌似不怎么需要用 eel.expose(js_fun); function js_fun(a){ return('这是调用js中函数返回的结果:' + a); } </script> </body> </html>
能用HTML做界面的话,颜值肯定有保证了,接下来就是继续研究python源代码转EXE或者加密打包的问题了,还有~不知道如果配上vue.js的话会不会飞起来?
以上来自:https://blog.csdn.net/lpwmm/article/details/102965286
提升一下,直接用vue+vant的前端做python前端:
py部分
import eel import time # 定义html文件所在文件夹名称 eel.init('web') @eel.expose # 使用装饰器,类似flask里面对路由的定义 def py_fun(a): time.sleep(2) return [t*2 for t in a] eel.start('test.html', port=0, size=(800,400))
test.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <title>Eel演示</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"> <script src="/eel.js"></script> <script src="css/vue.js"></script> <script src="css/vant.min.js"></script> <link rel="stylesheet" href="css/vant.css"> <link rel="stylesheet" href="css/hwj.css"> </head> <body> <div id="vuebox"> <!--内容开始--> <p v-for="item in test">{{item}}</p> <van-button type="primary" @click="doThis">主要按钮</van-button> <!--内容结束--> </div><!--vuebox--> <script> const app=new Vue({///////////////////////////start vue el:'#vuebox', data(){return{ test:[1,2,3,4] }}, methods:{ loading(){this.$toast({type: 'loading', message: '正在加载', forbidClick: true, duration: 0});}, loaded(){this.$toast.clear();this.$toast({type: 'success', message: '加载成功', forbidClick: true, duration: 500});}, async doThis(){ this.loading(); this.test = await eel.py_fun(this.test)(); this.loaded(); } }, mounted:function(){ var d = new Date(); console.log(d) }, });///////////////////////////////////end vue </script> </body> </html>
以上用到的js,css来自vant2的页面:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vant@2.12/lib/index.css" /> <!-- 引入 Vue 和 Vant 的 JS 文件 --> <script src="https://cdn.jsdelivr.net/npm/vue@2.6/dist/vue.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/vant@2.12/lib/vant.min.js"></script>
运行完,打包:
python -m eel t1.py web --onefile --noconsole --noconfirm
python -m eel 程序包.py web --noconsole --noconfirm
pyinstaller -F --noconsole -i i.ico 运行.py
完美
eel的说明文档: