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

如何保存ipyleaflet自定义Marker列表并后续加载?

问题

我需要保存ipyleaflet的自定义标记列表,后续加载到另一幅地图中。我自定义了MarkerCustom类,为标记添加了duration属性,该类可正常工作。由于后续要将标记拆分到不同集群,目前不想把它们保存为单个集群。

自定义类代码:

from traitlets import List
import ipyleaflet
from ipywidgets import HTML

class MarkerCustom(ipyleaflet.Marker):
    duration = List().tag(sync=True, o=True) 

标记存储在长列表mark中,示例如下:

mark[0] = MarkerCustom(location=[df.loc[index]['latitude'], df.loc[0]['longitude']], 
                       icon=icon, draggable=False, title=tooltip, 
                       duration=duration_list, popup=HTML('custom text0'))
mark[1] = MarkerCustom(location=[df.loc[1]['latitude'], df.loc[1]['longitude']], 
                       icon=icon, draggable=False, title=tooltip, 
                       duration=duration_list, popup=HTML('custom text1'))

尝试过shelve、pickle、json方案均失败:

  • 使用pickle时出现TypeError: cannot pickle '_hashlib.HMAC' object错误
  • 尝试用geojson库并实现__geo_interface__属性时,出现TypeError: Object of type set is not JSON serializable错误

希望能直接保存整个mark列表,而非逐个处理单个标记。

解决方案

由于ipyleaflet的Marker是Widget子类,包含大量不可序列化的交互属性(如内部trait状态、HMAC对象),无法直接序列化保存。可行方案是提取标记的核心可序列化数据,保存后再重建标记对象。

步骤1:提取并保存标记核心数据

import json
from ipyleaflet import Marker
from ipywidgets import HTML

# 遍历标记列表,提取可序列化的核心信息
mark_data = []
for marker in mark:
    # 提取HTML弹窗内容
    popup_content = marker.popup.value if isinstance(marker.popup, HTML) else None
    
    # 提取图标属性(支持Icon/FontAwesomeIcon等)
    icon_data = {}
    if marker.icon:
        # 记录图标类名,用于后续重建
        icon_data['class'] = marker.icon.__class__.__name__
        # 提取所有可序列化的图标属性
        for attr in dir(marker.icon):
            if not attr.startswith('_') and isinstance(getattr(marker.icon, attr), (str, int, float, list, dict, bool)):
                icon_data[attr] = getattr(marker.icon, attr)
    
    # 整理当前标记的所有核心数据
    marker_info = {
        'location': marker.location,
        'duration': marker.duration,
        'title': marker.title,
        'draggable': marker.draggable,
        'popup_content': popup_content,
        'icon_data': icon_data
    }
    mark_data.append(marker_info)

# 保存到JSON文件(通用且易读)
with open('markers_data.json', 'w', encoding='utf-8') as f:
    json.dump(mark_data, f, indent=2)

步骤2:加载数据并重建标记列表

import json
from ipyleaflet import Marker, Icon, FontAwesomeIcon
from ipywidgets import HTML
from traitlets import List

# 重新定义自定义标记类
class MarkerCustom(Marker):
    duration = List().tag(sync=True, o=True)

# 加载保存的标记数据
with open('markers_data.json', 'r', encoding='utf-8') as f:
    mark_data = json.load(f)

# 重建标记列表
mark = []
for data in mark_data:
    # 重建图标对象
    icon = None
    if data['icon_data']:
        # 根据保存的类名获取图标类
        icon_class = globals()[data['icon_data']['class']]
        # 移除类名字段,剩余参数用于实例化图标
        icon_kwargs = {k: v for k, v in data['icon_data'].items() if k != 'class'}
        icon = icon_class(**icon_kwargs)
    
    # 重建弹窗
    popup = HTML(data['popup_content']) if data['popup_content'] else None
    
    # 创建自定义标记实例
    marker = MarkerCustom(
        location=data['location'],
        duration=data['duration'],
        title=data['title'],
        draggable=data['draggable'],
        icon=icon,
        popup=popup
    )
    mark.append(marker)

说明

  • 该方案通过提取标记的location、duration、title等核心属性,以及弹窗、图标的可序列化数据,避开了Widget类中不可序列化的部分。
  • JSON格式保存的数据兼容性强,可跨环境读取;如果需要更高的存储效率,也可以将json.dump/json.load替换为pickle.dump/pickle.load。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 18:46:12