如何在Bokeh中嵌入自定义CSS字体以支持export_png导出
解决Bokeh导出PNG时嵌入自定义CSS字体的问题
我来帮你搞定这个问题——在Bokeh里用自定义字体做图表,网页展示没问题,但导出PNG时字体不生效的情况确实常见,核心原因是PhantomJS/Selenium在渲染导出时,没法正确加载外部CSS链接,必须把字体和样式内联到生成的HTML中才行。下面是具体的可行方案:
核心思路
- 将自定义字体文件转换为Base64编码,直接嵌入CSS中(避免依赖外部文件,确保导出时PhantomJS能获取到字体)
- 通过Bokeh的
Div组件插入内联的<style>标签,让样式被导出流程中的渲染引擎加载 - 显式设置图表坐标轴的字体为自定义字体名称(配合CSS的强制覆盖,确保样式生效)
完整代码示例
from bokeh.plotting import figure, export_png from bokeh.models import Div from bokeh.io import curdoc import base64 # 1. 读取自定义字体并转换为Base64编码 # 替换成你的字体文件路径,比如"my_custom_font.ttf" with open("my_custom_font.ttf", "rb") as font_file: font_base64 = base64.b64encode(font_file.read()).decode("utf-8") # 2. 定义内联CSS,包含字体声明和坐标轴样式覆盖 custom_css = f""" <style> @font-face {{ font-family: 'MyCustomFont'; src: url(data:font/truetype;base64,{font_base64}) format('truetype'); font-weight: normal; font-style: normal; }} /* 强制覆盖Bokeh默认的坐标轴标签和刻度字体 */ .bk-axis-label, .bk-tick-label {{ font-family: 'MyCustomFont', sans-serif !important; }} </style> """ # 3. 将内联CSS添加到Bokeh文档中 curdoc().add_root(Div(text=custom_css)) # 4. 创建图表并设置字体 p = figure(title="自定义字体测试图表", x_axis_label="X轴示例", y_axis_label="Y轴示例") p.line([1, 2, 3, 4], [10, 20, 15, 25]) # 显式设置坐标轴字体(配合CSS双重保险) p.xaxis.axis_label_text_font = "MyCustomFont" p.yaxis.axis_label_text_font = "MyCustomFont" p.xaxis.major_label_text_font = "MyCustomFont" p.yaxis.major_label_text_font = "MyCustomFont" # 5. 导出PNG export_png(p, filename="custom_font_plot.png")
为什么这个方案有效?
- 用Base64嵌入字体:把字体文件直接编码成字符串放进CSS,不需要PhantomJS访问外部资源,彻底解决导出时字体加载失败的问题
- 内联
<style>通过Div插入:Bokeh的导出流程会把这个Div的内容包含到生成的临时HTML中,PhantomJS渲染时会直接解析这个内联样式 !important强制覆盖:Bokeh自带的样式优先级可能较高,用!important确保自定义字体样式能生效
额外注意事项
- 如果你的字体是其他格式(比如OTF、WOFF),只需要修改
@font-face里的data:类型和format()参数即可(比如font/opentype对应OTF) - 确保自定义字体的名称(
MyCustomFont)在CSS和Bokeh的字体设置中保持一致
内容的提问来源于stack exchange,提问作者user3076411
相关产品推荐
相关产品推荐

