如何使用Tkinter GUI启动运行bokeh serve脚本graph2d.py
问题描述
我有一份bokeh可视化代码,原本需要在终端输入如下命令才可启动运行:
bokeh serve --show graph2d.py
需要实现通过Tkinter编写的GUI程序触发运行上述bokeh脚本graph2d.py,现有Tkinter界面代码如下,尝试直接导入graph2d模块调用始终无法成功运行:
import tkinter as tk from tkinter import * import graph2d """import tkinter as Tk from tkinter import ttk""" window = Tk() window.title("Welcome to PokerScatter app") """ WINDOW_SIZE = "600x400" root = tk.Tk() root.geometry(WINDOW_SIZE) """ selected = IntVar() rad1 = Radiobutton(window,text='2d Scatter', value=1, variable=selected, command=graph2d) rad2 = Radiobutton(window,text='3d Scatter', value=2, variable=selected) rad3 = Radiobutton(window,text='Pie Chart', value=3, variable=selected) rad4 = Radiobutton(window,text='Histogram', value=4, variable=selected) def clicked(): print("Processing") btn = Button(window, text="Show", command=clicked) rad1.grid(column=0, row=0) rad2.grid(column=2, row=0) rad3.grid(column=0, row=1) rad4.grid(column=2, row=1) btn.grid(column=6, row=0) window.mainloop()
解决方案
直接导入graph2d模块的写法无法生效,核心原因是bokeh serve本质是启动独立的Web服务进程,直接导入模块不会加载bokeh的服务运行环境,自然无法弹出可视化页面。正确实现方式是通过Python内置的subprocess模块调用bokeh启动命令,用非阻塞方式启动进程避免卡死Tkinter界面。
修改后的可运行代码:
import tkinter as tk from tkinter import * import subprocess import sys import os window = Tk() window.title("Welcome to PokerScatter app") selected = IntVar() def run_bokeh_script(script_name): script_path = os.path.abspath(script_name) # 非阻塞启动bokeh服务,Windows下隐藏额外终端窗口 startup_params = {} if sys.platform == "win32": startup_params["creationflags"] = subprocess.CREATE_NO_WINDOW subprocess.Popen( [sys.executable, "-m", "bokeh", "serve", "--show", script_path], **startup_params ) def clicked(): print("Processing") selected_opt = selected.get() if selected_opt == 1: run_bokeh_script("graph2d.py") # 其余3D散点图、饼图、直方图的启动逻辑按相同格式补充即可 rad1 = Radiobutton(window,text='2d Scatter', value=1, variable=selected) rad2 = Radiobutton(window,text='3d Scatter', value=2, variable=selected) rad3 = Radiobutton(window,text='Pie Chart', value=3, variable=selected) rad4 = Radiobutton(window,text='Histogram', value=4, variable=selected) btn = Button(window, text="Show", command=clicked) rad1.grid(column=0, row=0) rad2.grid(column=2, row=0) rad3.grid(column=0, row=1) rad4.grid(column=2, row=1) btn.grid(column=6, row=0) window.mainloop()
关键说明
- 不要把导入的模块直接作为Radiobutton/Button的command参数,command只接受可调用的函数对象,传模块不会触发任何执行逻辑
- 必须用
subprocess.Popen而非subprocess.run启动进程,后者会阻塞Tkinter主循环,导致界面无响应 - 代码中自动获取当前Python解释器路径启动bokeh,避免系统多Python环境下找不到bokeh命令的问题
- 如果bokeh脚本不和Tkinter脚本存放在同一目录,把
run_bokeh_script传入的文件名替换成对应脚本的绝对路径即可
内容的提问来源于stack exchange,提问作者javi topo
相关产品推荐
相关产品推荐

