streamlit+pywebview,纯python以前后端形式写桌面应用

1、VSCode

VSCode
VSCode扩展:Python

2、配置PowerShell执行策略

以管理员身份运行PowerShell,运行Set-ExecutionPolicy RemoteSigned,并输入Y,回车确认

3、配置Python环境

  1. 只安装Python:华为镜像阿里镜像newbePython官网ftp地址Python官网中文页面
  2. Python嵌入版:Python3.11.3下载页面Python3.11.3嵌入版下载直链、各个镜像的嵌入式压缩包
  3. 虚拟环境或版本管理:venvvirtualenvvirtualenvwrapperpoetrycondaAnacondaMiniconda清华镜像pyenv-win的Github仓库pyenv-virtualenvpipenv

streamlit的入门文档中,支持的 Python 版本为 3.7 - 3.11

本篇文章使用嵌入式Python3.11.3 64位python-3.11.3-embed-amd64.zip
解压为python-3.11.3-embed-amd64文件夹,改名为python3.11.3-e

4、调整项目结构

新建文件夹histreamlit,将python3.11.3-e放到histreamlit文件夹内
路径:histreamlit\python3.11.3-e

新建子文件夹histreamlit,路径:histreamlit\histreamlit
添加一个ico格式图片,路径:histreamlit\2530812_crest_crown_general_item_jwellery_icon.ico
在这里插入图片描述

5、继续配置Python环境

.\python3.11.3-e\pip.ini,新建该文件,内容如下

[global]
index-url = https://mirrors.aliyun.com/pypi/simple
trusted-host = mirrors.aliyun.com
timeout = 120

下载get-pip.py,放进python3.11.3-e文件夹
运行.\python3.11.3-e\python.exe .\python3.11.3-e\get-pip.py

编辑histreamlit\python3.11.3-e\python311._pth文件,将#import site改为import site

安装black
.\python3.11.3-e\python.exe -m pip install -U black --user

6、安装streamlit

.\python3.11.3-e\python.exe -m pip install streamlit

7、运行streamlit自带hello项目

.\python3.11.3-e\Scripts\streamlit.exe hello
在这里插入图片描述
自动启动浏览器显示界面
在这里插入图片描述
Ctrl+C停止运行(反应极慢,不如直接关了命令行窗口另开一个)

8、复制一下官方demo

在这里插入图片描述
新建文件histreamlit\histreamlit\main.py
在这里插入图片描述
使用 VSCode 打开histreamlit文件夹,右下角选择解释器,点击Enter interpreter path…,点击Find…,选择.\python3.11.3-e\python.exe,点击Select Interpreter

编辑文件histreamlit\histreamlit\main.py(复制一下官方的demo)

import streamlit as st
import numpy as np
import time

progress_bar = st.sidebar.progress(0)
status_text = st.sidebar.empty()
last_rows = np.random.randn(1, 1)
chart = st.line_chart(last_rows)

for i in range(1, 101):
    new_rows = last_rows[-1, :] + np.random.randn(5, 1).cumsum(axis=0)
    status_text.text("%i%% Complete" % i)
    chart.add_rows(new_rows)
    progress_bar.progress(i)
    last_rows = new_rows
    time.sleep(0.05)

progress_bar.empty()

# Streamlit widgets automatically run the script from top to bottom. Since
# this button is not connected to any other logic, it just causes a plain
# rerun.
st.button("Re-run")

9、运行

运行.\python3.11.3-e\Scripts\streamlit.exe run .\histreamlit\main.py

10、静默运行,不启动浏览器

运行.\python3.11.3-e\Scripts\streamlit.exe run .\histreamlit\main.py --server.headless=true --browser.serverAddress="localhost"

11、安装PyWebview

.\python3.11.3-e\Scripts\pip.exe install pywebview

12、新建文件pwv.py

histreamlit\histreamlit\pwv.py

import webview
import streamlit.web.bootstrap as bootstrap
import multiprocessing as mp
from multiprocessing import Process
import socket
from http.server import HTTPServer
import os
import signal


def check_port_in_use(port):
    try:
        # 创建一个HTTPServer实例
        httpd = HTTPServer(("", port), None)
        # 关闭HTTPServer实例
        httpd.server_close()
        # 如果没有抛出异常,说明端口可以使用
        return False
    except socket.error:
        # 如果抛出异常,说明端口已经被占用
        return True


def guess_streamlit_port():
    for p in range(8501, 8601):
        if not check_port_in_use(p):
            # print(f"端口 {p} 可以使用")
            return p
        else:
            # print(f"端口 {p} 已被使用")
            pass


def stre(q: mp.Queue):
    q.put(os.getpid())

    # .\python3.11.3-e\Scripts\streamlit.exe run .\histreamlit\main.py --server.headless=true --browser.serverAddress="localhost"
    flag_options = {
        "server.headless": True,
        "global.developmentMode": False,
        "browser.serverAddress": "localhost",
    }
    bootstrap.load_config_options(flag_options=flag_options)
    flag_options["_is_running_with_streamlit"] = True
    bootstrap.run(
        "main.py", "../python3.11.3-e/Scripts/streamlit.exe run", [], flag_options
    )


def webv(q: mp.Queue, port):
    q.put(os.getpid())

    def on_closing():
        print("Closing window...")

        pids = [q.get(), q.get()]
        # 分辨出哪个是streamlit,将streamlit放到第0位
        if pids[0] == os.getpid():
            pids.reverse()
        pids.append(os.getppid())

        for p in pids:
            os.kill(p, signal.SIGTERM)
        # return True 表示webview将关闭。不过无所谓,满门抄斩了已经
        return True

    win = webview.create_window(
        "histreamlit", f"http://localhost:{port}/", confirm_close=True
    )
    win.events.closing += on_closing
    webview.start()


if __name__ == "__main__":
    port = guess_streamlit_port()

    q = mp.Queue()
    processes: list[Process] = []

    webv_process = mp.Process(name="webv_process", target=webv, args=((q, port)))
    webv_process.start()
    processes.append(webv_process)

    stre_process = mp.Process(name="stre_process", target=stre, args=((q,)))
    stre_process.start()
    processes.append(stre_process)

    for p in processes:
        p.join()
    pass

13、运行streamlit+pywebview

.\python3.11.3-e\python.exe .\histreamlit\pwv.py

14、运行streamlit+pywebview(bat脚本)

新建文件histreamlit\histreamlit\start.bat

@echo off
cd /d %~dp0
..\python3.11.3-e\python.exe .\pwv.py

双击start.bat运行

15、编写vbs,启动不显示控制台

histreamlit\start.vbs

set WshShell = createobject("WScript.Shell")           ' 创建一个对象引用
dim currentDir                                         ' 创建变量
currentDir = WshShell.CurrentDirectory                 ' 获取当前文件夹
WshShell.run currentDir & "/histreamlit/start.bat", 1  ' 运行bat, 0表示不显示窗口, 1表示显示窗口

histreamlit\start_noconsole.vbs

set WshShell = createobject("WScript.Shell")           ' 创建一个对象引用
dim currentDir                                         ' 创建变量
currentDir = WshShell.CurrentDirectory                 ' 获取当前文件夹
WshShell.run currentDir & "/histreamlit/start.bat", 0  ' 运行bat, 0表示不显示窗口, 1表示显示窗口

唯一的区别一个参数用的是1,另一个用的是0
分别双击vbs脚本运行

16、将vbs转换为exe

注:之前截图中带有gb18030字样的vbs只是文本编码是gb18030,因为用来vbs转exe的软件不认识utf8,注释中文字会乱码而已


start_gb18030.vbsstart.exe为例
在这里插入图片描述
勾选图标,选择ico文件
EXE格式,改为32位 | Windows(隐形),(这里的隐形是vbs的隐形,不是bat,python的窗口隐形)
勾选启用 UPX 压缩
点击工具栏的转换(圆底齿轮图标),文件名起名为start.exe保存,软件将生成exe文件
在这里插入图片描述

17、最终效果

运行start.exe
在这里插入图片描述
关闭pywebview的窗口cmd会显示一下Closing window...,然后就消失了
在这里插入图片描述
运行start_noconsole.exe是一样的,就是没有控制台窗口而已,更像一个桌面应用了

18、怎么分发

有什么可分发的,文件夹发给别人运行exe不就得了,还想咋分发,就这玩意还想加密啊,用服务器呗,肯定密



7、(失败)参考议题,制作桌面端应用

(失败原因:npm run dump histreamlit numpy一直运行个没完,输出停滞)
Streamlit - #1370议题
@stlite/desktop - README.md

8、(失败)安装nvm

访问下载地址下载安装nvm:
百度云分享
官网直装链接
nvm的github发行界面下载nvm-setup.exe
GitCode镜像下载nvm-setup.exe(登录获取下载链接,下载链接还是Github的,唯一的作用就是挑选版本的时候快点)

9、(失败)配置nvm

nvm install lts安装最新版本的Node.js,本文安装的是18.16.0
nvm use lts启用这个版本
运行cmd /c "nvm -v && node -v && npm -v",正常输出版本号说明安装完成

10、(失败)配置npm镜像

npm config set registry https://registry.npmmirror.com

11、(失败)准备使用stlite

histreamlit-ehistreamlit两个文件夹应当同级,它们是独立的

md histreamlit-e
cd .\histreamlit-e\
npm init -y
code .
将编辑文件.\histreamlit-e\package.json,改为以下内容

{
  "name": "histreamlit-e",
  "version": "0.1.0",
  "main": "./build/electron/main.js",
  "scripts": {
    "dump": "dump-stlite-desktop-artifacts",
    "serve": "cross-env NODE_ENV=production electron .",
    "pack": "electron-builder --dir",
    "dist": "electron-builder",
    "postinstall": "electron-builder install-app-deps"
  },
  "build": {
    "files": ["build/**/*"],
    "directories": {
      "buildResources": "assets"
    }
  },
  "devDependencies": {
    "@stlite/desktop": "^0.25.0",
    "cross-env": "^7.0.3",
    "electron": "23.1.1",
    "electron-builder": "^23.6.0"
  }
}

访问以下npm包,查看版本并修改package.json
在这里插入图片描述
@stlite/desktop - npm
cross-env - npm
electron - npm
electron-builder - npm
例如以下截图:
在这里插入图片描述

12、(失败)安装依赖

histreamlit-e目录中
运行cmd /c "set ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/&& npm install"

提示高危:6 high severity vulnerabilities
运行cmd /c "npm audit fix --force --registry=https://registry.npmjs.org"解决高危

13、(失败)将histreamlit的内容写进histreamlit-e

新建文件.\histreamlit-e\histreamlit\streamlit_app.py,内容与.\histreamlit\histreamlit\main.py一致

14、(失败)运行

histreamlit-e目录中
npm run dump histreamlit numpy
一直运行不完成,没有CPU或者磁盘占用,也许在下载什么东西但是没有timeout功能导致的





请添加图片描述

作为AI助手,我可以为您提供一些关于使用HTML、CSS、JS进行前端登录和使用Python做后端的基本信息。 1. HTML、CSS、JS登录 HTML、CSS、JS是用于Web开发的三种基础语言,其中HTML用于定义Web页面的内容结构,CSS用于定义页面的样式和布局,JS则用于实现页面的交互效果和动态效果。 在Web开发中,登录功能是非常常见的一个功能,下面是一个使用HTML、CSS、JS实现登录的示例: HTML代码: ```html <form> <label for="username">用户名:</label> <input type="text" id="username" name="username"><br><br> <label for="password">密码:</label> <input type="password" id="password" name="password"><br><br> <input type="button" value="登录" onclick="login()"> </form> ``` CSS代码: ```css form { width: 300px; margin: 0 auto; text-align: center; } label { display: inline-block; width: 80px; text-align: right; } input[type="text"], input[type="password"] { width: 150px; height: 20px; margin: 5px; padding: 5px; border-radius: 5px; border: 1px solid #ccc; } input[type="button"] { width: 100px; height: 30px; margin-top: 10px; border-radius: 5px; border: none; background-color: #007acc; color: #fff; } input[type="button"]:hover { background-color: #005c99; cursor: pointer; } ``` JS代码: ```javascript function login() { var username = document.getElementById("username").value; var password = document.getElementById("password").value; if (username == "admin" && password == "123456") { alert("登录成功!"); } else { alert("用户名或密码错误!"); } } ``` 2. Python做后端 Python是一种高级编程语言,广泛用于Web开发、数据分析、人工智能等领域。在Web开发中,Python可以用于实现后端服务,处理前端发送的请求并返回相应的数据。 下面是一个使用Python实现登录功能的示例: Python代码: ```python from flask import Flask, request, jsonify app = Flask(__name__) @app.route("/login", methods=["POST"]) def login(): username = request.form["username"] password = request.form["password"] if username == "admin" and password == "123456": return jsonify({"code": 200, "msg": "登录成功!"}) else: return jsonify({"code": 400, "msg": "用户名或密码错误!"}) if __name__ == "__main__": app.run() ``` 在这个例子中,我们使用了Flask框架来实现后端服务,定义了一个/login接口,并在接口中处理了前端发送的请求,判断用户名和密码是否正确,并返回相应的信息。通过这种方式,前端和后端可以实现数据的交互和处理,从而实现完整的Web应用程序。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值