You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Panel中template.serveable异常:下拉框切换页面不更新且端口占用

问题

本地存储4个CSV文件,每个对应店铺详情,包含ItemNumber、ItemName、ItemBrand、ItemCost字段。使用Python Panel将CSV转为交互式数据框在浏览器展示,程序启动后浏览器可正常打开,但切换下拉框选择不同文件时,页面内容不更新,且报错:

2023-06-16 23:38:24,500 ERROR: panel.reactive - Callback failed for object named "Select File Name" changing property {'value': 'File2'} . OSError: [WinError 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted

已尝试在切换下拉框时停止旧服务并启动新服务避免端口冲突,但未生效。使用template.show()会随机端口启动新服务,但需要固定端口展示不同下拉框对应的内容。原代码如下:

#!/usr/bin/env python3

import pandas as pd
from pathlib import Path
import panel as pn
import hvplot.pandas

fileName = "File1"
df_file_name = fileName + "_df.csv"
df_filepath = Path('C:\\Users\\user1\\MyPythonApp\\' + df_file_name)
serveable = None

def dfToDisplay(file):
    global serveable  # Access the 'serveable' variable

    # Stop the previous 'servable' if it exists
    if serveable is not None:
        serveable.stop()
        time.sleep(10)
    if type(file) == str:
        filenm = file
    else:
        filenm = file[-2]

    df_path = Path("C:\\Users\\user1\\MyPythonApp\\" + filenm + "_df.csv")
    displayDF = pd.read_csv(df_path)
    interactivedf = displayDF.interactive()
    itable = interactivedf.pipe(pn.widgets.Tabulator, pagination='local', page_size=50, layout='fit_data', theme='default', disabled=True, widths={'index': '70', 'ItemNumber': '130', 'ItemName': '200', 'ItemBrand': '150', 'ItemCost': '900'})
    template = pn.template.FastListTemplate(title='Blah blah Details', sidebar=['Filename', dropdown], logo='https://abccorp.com/logo.svg', main=[itable.panel()])
    serveable = pn.serve(template, port=20001, show=False)

dropdown = pn.widgets.Select(name='Select File Name', options=['File1', 'File2', 'File3', 'File4'])
dropdown.param.watch(dfToDisplay, 'value')
dfToDisplay(fileName)
解决方案

核心问题是错误地在回调里重复启动pn.serve服务,Panel的正确做法是只启动一次服务,通过更新组件内容实现页面刷新,而非重启服务。修复后的代码如下:

#!/usr/bin/env python3
import pandas as pd
from pathlib import Path
import panel as pn
import hvplot.pandas

# 初始化Tabulator组件所需的Panel扩展
pn.extension('tabulator')

# 定义文件基础路径
BASE_PATH = Path('C:\\Users\\user1\\MyPythonApp\\')

# 创建下拉选择组件
dropdown = pn.widgets.Select(name='Select File Name', options=['File1', 'File2', 'File3', 'File4'])

# 初始化Tabulator表格组件,配置固定参数
itable = pn.widgets.Tabulator(
    pagination='local', 
    page_size=50, 
    layout='fit_data', 
    theme='default', 
    disabled=True, 
    widths={'index': '70', 'ItemNumber': '130', 'ItemName': '200', 'ItemBrand': '150', 'ItemCost': '900'}
)

# 定义表格数据更新函数
def update_table(file_name):
    # 拼接目标文件路径
    df_path = BASE_PATH / f"{file_name}_df.csv"
    # 读取CSV数据
    displayDF = pd.read_csv(df_path)
    # 更新表格组件的数据内容
    itable.value = displayDF

# 绑定下拉框选择事件到更新函数
dropdown.param.watch(lambda event: update_table(event.new), 'value')

# 初始化加载第一个文件的数据
update_table('File1')

# 创建页面模板并挂载组件
template = pn.template.FastListTemplate(
    title='Blah blah Details', 
    sidebar=['Filename', dropdown], 
    logo='https://abccorp.com/logo.svg', 
    main=[itable]
)

# 仅启动一次服务,固定端口20001
pn.serve(template, port=20001, show=True)

关键修改说明:

  1. 移除重复服务启动逻辑:只在程序末尾启动一次pn.serve,彻底避免端口冲突问题。
  2. 组件内容更新替代服务重启:通过修改Tabulator的value属性刷新表格数据,这是Panel原生的交互更新方式,无需重启服务。
  3. 简化回调逻辑:直接通过event.new获取下拉框选中的文件名,省去复杂的参数类型判断。
  4. 规范路径处理:使用Path对象的/操作符拼接路径,避免字符串拼接的潜在错误。
  5. 初始化组件扩展:添加pn.extension('tabulator')确保Tabulator组件正常渲染。

内容的提问来源于stack exchange,提问作者Thushar Mohan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 11:27:34