散景的export_png函数非常慢

时间:2019-12-04 15:22:51

标签: python python-3.x phantomjs bokeh

我有一个非常简单的Python脚本(除了最后一行,它基本上是瞬时执行的):

  from bokeh.plotting import figure
  from bokeh.io import export_png

  x_labels = ['AAA','BBB','CCC']
  y_values = [5,7,2]
  p = figure(title='test', x_range=x_labels, plot_height=300, plot_width=500)
  c = p.vbar(x=x_labels, top=y_values, width=0.15, line_color=None)

  export_png(p, filename=r'C:\MyImage.png')  #  <--- takes very long

带有export_png的最后一行大约需要5-10秒。仅重新运行最后一行会更快(第二到第二秒)。如此看来,它“热身”了。 但是我可以做些什么来加快速度,还是这是已知的“功能”?


我在所有最新的bokeh版本(1.0.2、1.2.0、1.4.0)上都尝试过此方法,但所有结果均相同。我的PhantomJS的版本为2.1.1,其路径os.environ.get('BOKEH_PHANTOMJS_PATH')根据需要设置为C:\\Users\\USERNAME\\AppData\\Roaming\\npm\\node_modules\\phantomjs-prebuilt\\lib\\phantom\\bin\\phantomjs.exe

1 个答案:

答案 0 :(得分:1)

Bokeh是基于浏览器的绘图工具,因此,要导出为PNG,它必须:

  • 为无头浏览器(默认情况下为PhantomJS)启动外部webdriver进程
  • 序列化Bokeh内容的JSON表示并将其发送到该进程
  • 具有无头的浏览器流程:
    • 呈现所有Bokeh内容
    • 使用webdriver API捕获屏幕截图
    • 将图像数据发送回Python进程

创建webdriver进程会有一些开销,这就是为什么Bokeh默认在首次使用时会缓存它的原因。这就是为什么第一次出口花费更长的时间,而随后的出口更快的原因。但是这里实际上没有任何改进的空间。关于唯一可调整且可能会改变的事情是选择webdriver,例如您可以尝试使用Chromedriver或Geckodriver。 (事实上​​,由于PhantomJS已被弃用且不再维护,因此开放PR会默认切换到Geckodriver。)但是,我不确定这两者实际上都比PhantomJS快。

所有这些,即使是第一次渲染,我个人都没有经历10秒。作为参考,在相当老的Macbook上,上面的代码第一次渲染大约需要1.7秒,以后的渲染需要300ms:

In [8]: %time export_png(p, filename=r'C:\MyImage.png')
CPU times: user 107 ms, sys: 38.7 ms, total: 146 ms
Wall time: 1.69 s

In [9]: %time export_png(p, filename=r'C:\MyImage.png')
CPU times: user 74.6 ms, sys: 9.2 ms, total: 83.8 ms
Wall time: 319 ms
Out[9]: '/Users/bryan/tmp/C:\\MyImage.png'

我想可能会有平台差异,也许在Windows上启动进程的开销更高?您可以考虑的另一种方法是确保您的Selenium软件包是最新的,它们可能以某种方式进行了改进,并且可能会有所帮助。