matplotlib / matplotlib/ipympl

issue computing repr of `Figure`

未关闭
#115 14 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

主要语言
Jupyter Notebook
星标
1.7k
派生
234
PR 合并指标
30 天内没有已合并 PR

描述

Due to https://github.com/matplotlib/matplotlib/pull/10292 during a save operation we temporarily remove the manager

%matplotlib widget
import matplotlib.pyplot as plt
plt.plot(range(5))
fig = plt.gcf()

## new cell
fig

and you will get a traceback that looks like:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
~/.virtualenvs/bleeding/lib/python3.9/site-packages/IPython/core/formatters.py in __call__(self, obj)
    339                 pass
    340             else:
--> 341                 return printer(obj)
    342             # Finally look for special method names
    343             method = get_real_method(obj, self.print_method)

~/.virtualenvs/bleeding/lib/python3.9/site-packages/IPython/core/pylabtools.py in <lambda>(fig)
    242 
    243     if 'png' in formats:
--> 244         png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs))
    245     if 'retina' in formats or 'png2x' in formats:
    246         png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))

~/.virtualenvs/bleeding/lib/python3.9/site-packages/IPython/core/pylabtools.py in print_figure(fig, fmt, bbox_inches, **kwargs)
    126 
    127     bytes_io = BytesIO()
--> 128     fig.canvas.print_figure(bytes_io, **kw)
    129     data = bytes_io.getvalue()
    130     if fmt == 'svg':

~/source/p/mpl-master/lib/matplotlib/backend_bases.py in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, **kwargs)
   2058             if bbox_inches:
   2059                 if bbox_inches == "tight":
-> 2060                     renderer = _get_renderer(
   2061                         self.figure,
   2062                         functools.partial(

~/source/p/mpl-master/lib/matplotlib/backend_bases.py in _get_renderer(figure, print_method)
   1546     with cbook._setattr_cm(figure, draw=_draw):
   1547         try:
-> 1548             print_method(io.BytesIO())
   1549         except Done as exc:
   1550             figure._cachedRenderer, = exc.args

~/source/p/mpl-master/lib/matplotlib/backends/backend_agg.py in print_png(self, filename_or_obj, metadata, pil_kwargs, *args, **kwargs)
    533 
    534         else:
--> 535             FigureCanvasAgg.draw(self)
    536             renderer = self.get_renderer()
    537             with cbook._setattr_cm(renderer, dpi=self.figure.dpi), \

~/source/p/mpl-master/lib/matplotlib/backends/backend_agg.py in draw(self)
    391         self.renderer = self.get_renderer(cleared=True)
    392         # Acquire a lock on the shared font cache.
--> 393         with RendererAgg.lock, \
    394              (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar
    395               else nullcontext()):

~/source/other_source/cpython/Lib/contextlib.py in __enter__(self)
    111         del self.args, self.kwds, self.func
    112         try:
--> 113             return next(self.gen)
    114         except StopIteration:
    115             raise RuntimeError("generator didn't yield") from None

~/source/p/mpl-master/lib/matplotlib/backend_bases.py in _wait_cursor_for_draw_cm(self)
   2732         if self._draw_time - last_draw_time > 1:
   2733             try:
-> 2734                 self.set_cursor(cursors.WAIT)
   2735                 yield
   2736             finally:

~/source/p/mpl-master/lib/matplotlib/backends/backend_webagg_core.py in set_cursor(self, cursor)
    379     def set_cursor(self, cursor):
    380         if cursor != self.cursor:
--> 381             self.canvas.send_event("cursor", cursor=cursor)
    382         self.cursor = cursor
    383 

~/source/p/mpl-master/lib/matplotlib/backends/backend_webagg_core.py in send_event(self, event_type, **kwargs)
    344 
    345     def send_event(self, event_type, **kwargs):
--> 346         self.manager._send_event(event_type, **kwargs)
    347 
    348 

AttributeError: 'NoneType' object has no attribute '_send_event'

I thought we should be going through https://github.com/matplotlib/matplotlib/blob/59b5e0e873dd3420758498c90b15f7f70cb007da/lib/matplotlib/figure.py#L403-L408 but it looks like we are going trough a lambda from IPython core....

I think this could legitimately go against IPython, Matplotlib, or here. Leaving here as the "middle ground" ;)

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

使用 %matplotlib widget 在 notebook 中复现 traceback,然后检查 figure.py 第 403-408 行附近的 Figure repr 路径、IPython pylabtools formatter lambda,以及 set_cursor 和 send_event 附近的 backend_webagg_core.py。完成的标准是:绘图完成后能够显示 fig,并且渲染期间不会出现与 manager 相关的 AttributeError。

由索引模型根据 Issue 内容生成。

评估

技术栈
jupyter, matplotlib, python
领域
frontend
Issue 类型
缺陷
难度
4/5
预计耗时
3-5 天
活跃度
停滞
描述清晰度
需要澄清
新手友好度
35/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。