用途
pywebview
是一个轻量级Python库,用于创建桌面应用程序(GUI)。它通过嵌入Web浏览器组件(如Windows的Edge/IE、macOS的WebKit、Linux的GTK WebKit),允许开发者使用HTML/CSS/JavaScript构建界面,并用Python处理后端逻辑。这种方式结合了Web技术的灵活性和Python的强大功能,适合快速开发跨平台桌面应用。
特点
pip install pywebview
import webview
def print_message(message):
print(f"收到前端消息: {message}")
# 创建一个HTML字符串作为界面
html = """
PyWebView示例
"""
# 创建窗口并加载HTML
window = webview.create_window("PyWebView应用", html=html)
webview.start(gui=None, debug=True) # gui=None自动选择系统默认浏览器引擎
# app.py - Flask后端
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/')
def index():
return """
Flask + PyWebView应用
Hello from Flask!
"""
@app.route('/api/data')
def get_data():
return jsonify({"message": "这是来自Flask后端的数据!"})
if __name__ == '__main__':
# 开发环境:使用Flask内置服务器
app.run(debug=True, port=5000)
# desktop.py - PyWebView桌面应用包装
import webview
import threading
import subprocess
def run_flask():
# 启动Flask应用(开发环境)
subprocess.run(['python', 'app.py'])
if __name__ == '__main__':
# 在后台线程中启动Flask
flask_thread = threading.Thread(target=run_flask, daemon=True)
flask_thread.start()
# 创建PyWebView窗口,加载Flask应用
window = webview.create_window("桌面应用", "http://localhost:5000")
webview.start(gui=None, debug=True)
# app.py - Flask后端(生产环境)
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/')
def index():
return """
"""
@app.route('/api/data')
def get_data():
return jsonify({"message": "这是来自Flask后端的数据!"})
# 移除开发环境的app.run(),改为导出app实例
# server.py - 使用waitress启动Flask(生产环境)
from waitress import serve
from app import app
if __name__ == '__main__':
serve(app, host='127.0.0.1', port=5000, threads=8) # 生产环境使用waitress
# desktop.py - PyWebView桌面应用(生产环境)
import webview
import threading
import subprocess
def run_flask():
# 启动Flask应用(生产环境使用waitress)
subprocess.run(['python', 'server.py'])
if __name__ == '__main__':
# 在后台线程中启动Flask
flask_thread = threading.Thread(target=run_flask, daemon=True)
flask_thread.start()
# 创建PyWebView窗口,加载Flask应用
window = webview.create_window("桌面应用", "http://localhost:5000")
webview.start(gui=None, debug=False) # 生产环境关闭调试模式
为了将应用分发给最终用户,可以使用PyInstaller
或cx_Freeze
将Python代码打包成单个可执行文件:
# 使用PyInstaller打包
pyinstaller --onefile --windowed desktop.py
注意事项:
通过结合pywebview
、Flask
和waitress
,可以开发出兼具美观界面和强大功能的跨平台桌面应用:
以下是在Windows平台上结合PyWebView、Flask和Waitress的完整代码实现。代码分为三个主要文件,分别负责Flask后端、桌面应用包装和生产环境启动。
# app.py - Flask后端应用
from flask import Flask, jsonify, render_template_string
import os
app = Flask(__name__)
# 确保中文正常显示
app.config['JSON_AS_ASCII'] = False
# 首页路由
@app.route('/')
def index():
return render_template_string("""
PyWebView + Flask应用
PyWebView + Flask桌面应用
这是一个基于Web技术的跨平台桌面应用示例。
点击按钮查看结果...
""")
# API路由 - 返回JSON数据
@app.route('/api/data')
def get_data():
return jsonify({
"message": "这是来自Flask后端的数据!",
"timestamp": str(os.times()),
"platform": "Windows桌面应用"
})
# 导出Flask应用实例供其他模块使用
if __name__ == '__main__':
# 仅在直接运行此文件时使用Flask内置服务器(开发环境)
app.run(debug=True, port=5000)
# desktop_dev.py - 开发环境下的桌面应用启动脚本
import webview
import threading
import subprocess
import time
import sys
from flask import Flask
def run_flask():
"""在子进程中启动Flask开发服务器"""
# 确定Python可执行文件路径
python_exe = sys.executable
# 启动Flask应用
server = subprocess.Popen(
[python_exe, 'app.py'],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
universal_newlines=True
)
# 等待服务器启动
for line in server.stdout:
print(line.strip())
if 'Running on' in line:
break
return server
class Api:
"""供前端JavaScript调用的Python API"""
def multiply_numbers(self, a, b):
"""示例函数:计算两个数的乘积"""
return a * b
if __name__ == '__main__':
# 启动Flask服务器
flask_server = run_flask()
try:
# 创建API实例
api = Api()
# 创建PyWebView窗口
window = webview.create_window(
title="PyWebView桌面应用",
url="http://localhost:5000",
width=800,
height=600,
resizable=True,
fullscreen=False,
js_api=api # 暴露Python API给JavaScript
)
# 启动PyWebView主循环
webview.start(debug=True)
finally:
# 关闭Flask服务器
if flask_server:
flask_server.terminate()
flask_server.wait()
print("Flask服务器已关闭")
# desktop_prod.py - 生产环境下的桌面应用启动脚本
import webview
import threading
import subprocess
import time
import sys
from waitress import serve
from app import app
class Api:
"""供前端JavaScript调用的Python API"""
def multiply_numbers(self, a, b):
"""示例函数:计算两个数的乘积"""
return a * b
def run_waitress():
"""使用waitress启动Flask应用(生产环境)"""
print("正在启动Waitress服务器...")
serve(app, host='127.0.0.1', port=5000, threads=8)
if __name__ == '__main__':
# 在后台线程中启动waitress服务器
server_thread = threading.Thread(target=run_waitress, daemon=True)
server_thread.start()
# 等待服务器启动(给服务器一些时间初始化)
print("等待服务器启动...")
time.sleep(2)
try:
# 创建API实例
api = Api()
# 创建PyWebView窗口
window = webview.create_window(
title="PyWebView桌面应用",
url="http://localhost:5000",
width=800,
height=600,
resizable=True,
fullscreen=False,
js_api=api # 暴露Python API给JavaScript
)
# 启动PyWebView主循环(关闭调试模式)
webview.start(debug=False)
except Exception as e:
print(f"应用启动失败: {e}")
finally:
print("应用已关闭")
安装依赖:
pip install flask pywebview waitress
运行开发环境脚本:
python desktop_dev.py
打包应用(可选):
pyinstaller --onefile --windowed desktop_prod.py
直接运行生产环境脚本:
python desktop_prod.py
前后端交互:
fetch
调用Flask API(如/api/data
)。window.pywebview.api
调用Python函数(如multiply_numbers
)。界面特点:
Microsoft YaHei
字体)。这个实现可以作为Windows桌面应用的基础框架,你可以根据需要扩展Flask API或修改前端界面。
# create Desktop App by pywebview
"""
Replace the flask module with waitress module.
To avoid the warning: WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
"""
import webview
from flask import Flask, render_template_string
import threading
from waitress import serve
# Create a Flask application
app = Flask(__name__)
# Define the route
@app.route('/')
def index():
return render_template_string("""
Pywebview + Flask 示例
欢迎使用 Pywebview 和 Flask 构建的桌面应用!
Blog Site
""")
def create_webview():
# Define the URL of the Flask application to load
url = "http://127.0.0.1:5000"
# Create a window and load the specified URL
window = webview.create_window('Pywebview + Flask 应用', url)
# Run the application
webview.start()
if __name__ == '__main__':
# Start the Waitress server in a separate thread
def run_waitress():
try:
# Start Waitress to run the Flask application
serve(app, host='127.0.0.1', port=5000)
except Exception as e:
print(f"Error starting Waitress: {e}")
waitress_thread = threading.Thread(target=run_waitress)
waitress_thread.daemon = True
waitress_thread.start()
# Start pywebview
create_webview()