main.py
pip install fastapi uvicorn
import os.path
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse
app = FastAPI()
static_file_abspath = os.path.join(os.path.dirname(__file__), "static")
app.mount("/static", StaticFiles(directory=static_file_abspath), name="static")
@app.get("/")
def index():
return FileResponse(f"{static_file_abspath}/index.html")
if __name__ == '__main__':
import uvicorn
uvicorn.run(app)
client.py
# client.py
import random
import socket
import threading
import webview
from main import app
import uvicorn
def get_unused_port():
"""获取未被使用的端口"""
while True:
port = random.randint(1024, 65535) # 端口范围一般为1024-65535
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.bind(("localhost", port))
sock.close()
return port
except OSError:
pass
port = get_unused_port()
# 启动FastAPI服务
t = threading.Thread(target=uvicorn.run, args=(app,), kwargs={"port": port})
t.daemon = True
t.start()
# 在PyWebview应用程序中加载FastAPI应用程序的URL
webview.create_window('FastAPI Desktop', f'http://localhost:{port}')
webview.start()
build.py
from PyInstaller import __main__ as pyi
params = [
'-F',
# static目录纳入打包
'--add-data', 'static:static',
# 每次打包前清楚build 和 dist目录
'--clean',
# 无需用户确认
'--noconfirm',
'client.py'
]
# pyinstaller -F main.py
pyi.run(params)
备注
- python的exe的命令行窗口当然可以通过 -w取消掉的,加入params就可以了,调试的时候命令行需要看,所以开着方便调试。
- static 就是html的目录,vue生成的文件就放到这个目录中