SourceForge logo
SourceForge logo
Menu

matplotlib-devel

From: Pierre R. <co...@py...> - 2009年11月04日 22:22:40
Hi,
Some Spyder users have reported a critical bug occuring with matplotlib 
0.99's Qt4 backend and PyQt4 v4.6 (e.g. in Ubuntu Karmic).
Here is the traceback after calling 'plot([])', closing figure and 
calling again 'plot([])' (e.g. in an IPython session with options 
--pylab and --q4thread):
Traceback (most recent call last):
 File "/home/rick/Temp/untitled0.py", line 9, in <module>
 show()
 File "/usr/lib/pymodules/python2.6/matplotlib/backends/backend_qt4.py",
line 63, in show
 manager.window.show()
RuntimeError: underlying C/C++ object has been deleted
I found out that the 'destroyed()' signal (connected in class FigureManagerQT) is never emitted when figure is closed.
As a consequence, SIP is not very happy when trying to draw a deleted object...
I made the following changes to make it work:
# New class to clarify code in FigureManagerQT
class FigureWindow(QtGui.QMainWindow):
 def __init__(self, num, canvas, close_callback):
 super(FigureWindow, self).__init__()
 self.close_callback = close_callback
 self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
 self.setWindowTitle("Figure %d" % num)
 image = os.path.join(matplotlib.rcParams['datapath'],
 'images', 'matplotlib.png')
 self.setWindowIcon(QtGui.QIcon(image))
 self._destroying = False
 self.setCentralWidget(canvas)
 if matplotlib.is_interactive():
 self.show()
 
 def closeEvent(self, event):
 super(FigureWindow, self).closeEvent(event)
 self.close_callback()
class FigureManagerQT( FigureManagerBase ):
 """
 Public attributes
 canvas : The FigureCanvas instance
 num : The Figure number
 toolbar : The qt.QToolBar
 window : The qt.QMainWindow
 """
 def __init__( self, canvas, num ):
 if DEBUG: print 'FigureManagerQT.%s' % fn_name()
 FigureManagerBase.__init__( self, canvas, num )
 self.canvas = canvas
 # Give the keyboard focus to the figure instead of the manager
 self.canvas.setFocusPolicy( QtCore.Qt.ClickFocus )
 self.canvas.setFocus()
 self.window = FigureWindow(num, self.canvas, self._widgetclosed)
 self.toolbar = self._get_toolbar(self.canvas, self.window)
 self.window.addToolBar(self.toolbar)
 QtCore.QObject.connect(self.toolbar, QtCore.SIGNAL("message"),
 self.window.statusBar().showMessage)
# [...]
And we may now remove the "QtCore.QObject.disconnect" for the no longer existing signal 'destroyed()' in method 'FigureManagerQT.
destroy'.
HTH
Cheers,
Pierre
From: Pierre R. <co...@py...> - 2009年11月04日 22:30:10
A simpler fix would be:
 class FigureWindow(QtGui.QMainWindow):
 def __init__(self):
 super(FigureWindow, self).__init__()
 
 def closeEvent(self, event):
 super(FigureWindow, self).closeEvent(event)
 self.emit(QtCore.SIGNAL('destroyed()'))
and replacing QtGui.QMainWindow by FigureWindow in FigureManagerQT.
Pierre
Pierre Raybaut a écrit :
> Hi,
>
> Some Spyder users have reported a critical bug occuring with 
> matplotlib 0.99's Qt4 backend and PyQt4 v4.6 (e.g. in Ubuntu Karmic).
>
>
> Here is the traceback after calling 'plot([])', closing figure and 
> calling again 'plot([])' (e.g. in an IPython session with options 
> --pylab and --q4thread):
>
> Traceback (most recent call last):
> File "/home/rick/Temp/untitled0.py", line 9, in <module>
> show()
> File "/usr/lib/pymodules/python2.6/matplotlib/backends/backend_qt4.py",
> line 63, in show
> manager.window.show()
> RuntimeError: underlying C/C++ object has been deleted
>
>
> I found out that the 'destroyed()' signal (connected in class 
> FigureManagerQT) is never emitted when figure is closed.
> As a consequence, SIP is not very happy when trying to draw a deleted 
> object...
>
> I made the following changes to make it work:
>
> # New class to clarify code in FigureManagerQT
> class FigureWindow(QtGui.QMainWindow):
> def __init__(self, num, canvas, close_callback):
> super(FigureWindow, self).__init__()
> self.close_callback = close_callback
> self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
> self.setWindowTitle("Figure %d" % num)
> image = os.path.join(matplotlib.rcParams['datapath'],
> 'images', 'matplotlib.png')
> self.setWindowIcon(QtGui.QIcon(image))
> self._destroying = False
> self.setCentralWidget(canvas)
> if matplotlib.is_interactive():
> self.show()
> def closeEvent(self, event):
> super(FigureWindow, self).closeEvent(event)
> self.close_callback()
>
> class FigureManagerQT( FigureManagerBase ):
> """
> Public attributes
>
> canvas : The FigureCanvas instance
> num : The Figure number
> toolbar : The qt.QToolBar
> window : The qt.QMainWindow
> """
>
> def __init__( self, canvas, num ):
> if DEBUG: print 'FigureManagerQT.%s' % fn_name()
> FigureManagerBase.__init__( self, canvas, num )
> self.canvas = canvas
>
> # Give the keyboard focus to the figure instead of the manager
> self.canvas.setFocusPolicy( QtCore.Qt.ClickFocus )
> self.canvas.setFocus()
>
> self.window = FigureWindow(num, self.canvas, self._widgetclosed)
> self.toolbar = self._get_toolbar(self.canvas, self.window)
> self.window.addToolBar(self.toolbar)
> QtCore.QObject.connect(self.toolbar, QtCore.SIGNAL("message"),
> self.window.statusBar().showMessage)
> # [...]
>
> And we may now remove the "QtCore.QObject.disconnect" for the no 
> longer existing signal 'destroyed()' in method 'FigureManagerQT.
> destroy'.
>
> HTH
>
> Cheers,
> Pierre
>
>
From: Darren D. <dsd...@gm...> - 2009年11月06日 14:16:45
Hi Pierre,
Thanks for the report. I'll have a look as soon as I get a chance.
Darren
On Wed, Nov 4, 2009 at 5:29 PM, Pierre Raybaut <co...@py...> wrote:
> A simpler fix would be:
>
>    class FigureWindow(QtGui.QMainWindow):
>      def __init__(self):
>        super(FigureWindow, self).__init__()
>
>      def closeEvent(self, event):
>        super(FigureWindow, self).closeEvent(event)
>        self.emit(QtCore.SIGNAL('destroyed()'))
>
> and replacing QtGui.QMainWindow by FigureWindow in FigureManagerQT.
>
> Pierre
>
> Pierre Raybaut a écrit :
>> Hi,
>>
>> Some Spyder users have reported a critical bug occuring with
>> matplotlib 0.99's Qt4 backend and PyQt4 v4.6 (e.g. in Ubuntu Karmic).
>>
>>
>> Here is the traceback after calling 'plot([])', closing figure and
>> calling again 'plot([])' (e.g. in an IPython session with options
>> --pylab and --q4thread):
>>
>> Traceback (most recent call last):
>> File "/home/rick/Temp/untitled0.py", line 9, in <module>
>>  show()
>> File "/usr/lib/pymodules/python2.6/matplotlib/backends/backend_qt4.py",
>> line 63, in show
>>  manager.window.show()
>> RuntimeError: underlying C/C++ object has been deleted
>>
>>
>> I found out that the 'destroyed()' signal (connected in class
>> FigureManagerQT) is never emitted when figure is closed.
>> As a consequence, SIP is not very happy when trying to draw a deleted
>> object...
>>
>> I made the following changes to make it work:
>>
>> # New class to clarify code in FigureManagerQT
>> class FigureWindow(QtGui.QMainWindow):
>>  def __init__(self, num, canvas, close_callback):
>>    super(FigureWindow, self).__init__()
>>    self.close_callback = close_callback
>>    self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
>>    self.setWindowTitle("Figure %d" % num)
>>    image = os.path.join(matplotlib.rcParams['datapath'],
>>               'images', 'matplotlib.png')
>>    self.setWindowIcon(QtGui.QIcon(image))
>>    self._destroying = False
>>    self.setCentralWidget(canvas)
>>    if matplotlib.is_interactive():
>>      self.show()
>>      def closeEvent(self, event):
>>    super(FigureWindow, self).closeEvent(event)
>>    self.close_callback()
>>
>> class FigureManagerQT( FigureManagerBase ):
>>  """
>>  Public attributes
>>
>>  canvas   : The FigureCanvas instance
>>  num     : The Figure number
>>  toolbar   : The qt.QToolBar
>>  window   : The qt.QMainWindow
>>  """
>>
>>  def __init__( self, canvas, num ):
>>    if DEBUG: print 'FigureManagerQT.%s' % fn_name()
>>    FigureManagerBase.__init__( self, canvas, num )
>>    self.canvas = canvas
>>
>>    # Give the keyboard focus to the figure instead of the manager
>>    self.canvas.setFocusPolicy( QtCore.Qt.ClickFocus )
>>    self.canvas.setFocus()
>>
>>    self.window = FigureWindow(num, self.canvas, self._widgetclosed)
>>    self.toolbar = self._get_toolbar(self.canvas, self.window)
>>    self.window.addToolBar(self.toolbar)
>>    QtCore.QObject.connect(self.toolbar, QtCore.SIGNAL("message"),
>>                self.window.statusBar().showMessage)
>> # [...]
>>
>> And we may now remove the "QtCore.QObject.disconnect" for the no
>> longer existing signal 'destroyed()' in method 'FigureManagerQT.
>> destroy'.
>>
>> HTH
>>
>> Cheers,
>> Pierre
>>
>>
>
>
> ------------------------------------------------------------------------------
> Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
> trial. Simplify your report design, integration and deployment - and focus on
> what you do best, core application coding. Discover what's new with
> Crystal Reports now. http://p.sf.net/sfu/bobj-july
> _______________________________________________
> Matplotlib-devel mailing list
> Mat...@li...
> https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
>
From: Darren D. <dsd...@gm...> - 2009年11月06日 19:03:37
On Wed, Nov 4, 2009 at 5:29 PM, Pierre Raybaut <co...@py...> wrote:
> A simpler fix would be:
>
>    class FigureWindow(QtGui.QMainWindow):
>      def __init__(self):
>        super(FigureWindow, self).__init__()
>
>      def closeEvent(self, event):
>        super(FigureWindow, self).closeEvent(event)
>        self.emit(QtCore.SIGNAL('destroyed()'))
>
> and replacing QtGui.QMainWindow by FigureWindow in FigureManagerQT.
I am pretty sure this is not caused by matplotlib, but rather a
regression in PyQt4 that will be fixed in the next release. There is a
post on the PyQt mailing list titled "Regressions on destruction of
objects?" and a note in the development snapshots changelog. If I try
your example with PyQt4-4.5.4, it works fine, but it crashes with
4.6.1. I will revisit the issue once PyQt4-4.7 is released.
Darren
From: Pierre R. <co...@py...> - 2009年11月07日 14:53:14
>
> On Wed, Nov 4, 2009 at 5:29 PM, Pierre Raybaut <co...@py...> wrote:
> 
>> > A simpler fix would be:
>> >
>> > ? ? ? ?class FigureWindow(QtGui.QMainWindow):
>> > ? ? ? ? ? ?def __init__(self):
>> > ? ? ? ? ? ? ? ?super(FigureWindow, self).__init__()
>> >
>> > ? ? ? ? ? ?def closeEvent(self, event):
>> > ? ? ? ? ? ? ? ?super(FigureWindow, self).closeEvent(event)
>> > ? ? ? ? ? ? ? ?self.emit(QtCore.SIGNAL('destroyed()'))
>> >
>> > and replacing QtGui.QMainWindow by FigureWindow in FigureManagerQT.
>> 
>
> I am pretty sure this is not caused by matplotlib, but rather a
> regression in PyQt4 that will be fixed in the next release. There is a
> post on the PyQt mailing list titled "Regressions on destruction of
> objects?" and a note in the development snapshots changelog. If I try
> your example with PyQt4-4.5.4, it works fine, but it crashes with
> 4.6.1. I will revisit the issue once PyQt4-4.7 is released.
>
> Darren
> 
I completely agree -- in the meantime I checked that despite the 
QMainWindow instance has been destroyed, the 'destroyed()' signal is not 
emitted, so the problem is definitely coming from PyQt4, not matplotlib.
However, to help unfortunate users of PyQt4 v4.6 and v4.6.1, I've added 
the following workaround in Spyder (Spyder is monkey patching matplotlib 
anyway, to integrate mpl dockable figures in Spyder's GUI) -- other 
users may be interested to patch their matplotlib installation 
(matplotlib/backends/backend_qt4.py):
# Add this before "FigureManagerQT" class
class FigureWindow(QMainWindow):
 def __init__(self):
 super(FigureWindow, self).__init__() 
 def closeEvent(self, event):
 super(FigureWindow, self).closeEvent(event)
 if PYQT_VERSION_STR.startswith('4.6'):
 self.emit(SIGNAL('destroyed()'))
# Replace "QtGui.QMainWindow" by "FigureWindow" in "FigureManagerQT"'s 
constructor
I hope this will be fixed in v4.6.2.
Cheers,
Pierre
From: Darren D. <dsd...@gm...> - 2009年11月07日 20:30:21
On Sat, Nov 7, 2009 at 9:53 AM, Pierre Raybaut <co...@py...> wrote:
>>
>> On Wed, Nov 4, 2009 at 5:29 PM, Pierre Raybaut <co...@py...>
>> wrote:
>>
>>>
>>> > A simpler fix would be:
>>> >
>>> > ? ? ? ?class FigureWindow(QtGui.QMainWindow):
>>> > ? ? ? ? ? ?def __init__(self):
>>> > ? ? ? ? ? ? ? ?super(FigureWindow, self).__init__()
>>> >
>>> > ? ? ? ? ? ?def closeEvent(self, event):
>>> > ? ? ? ? ? ? ? ?super(FigureWindow, self).closeEvent(event)
>>> > ? ? ? ? ? ? ? ?self.emit(QtCore.SIGNAL('destroyed()'))
>>> >
>>> > and replacing QtGui.QMainWindow by FigureWindow in FigureManagerQT.
>>>
>>
>> I am pretty sure this is not caused by matplotlib, but rather a
>> regression in PyQt4 that will be fixed in the next release. There is a
>> post on the PyQt mailing list titled "Regressions on destruction of
>> objects?" and a note in the development snapshots changelog. If I try
>> your example with PyQt4-4.5.4, it works fine, but it crashes with
>> 4.6.1. I will revisit the issue once PyQt4-4.7 is released.
>>
>> Darren
>>
>
> I completely agree -- in the meantime I checked that despite the QMainWindow
> instance has been destroyed, the 'destroyed()' signal is not emitted, so the
> problem is definitely coming from PyQt4, not matplotlib.
>
> However, to help unfortunate users of PyQt4 v4.6 and v4.6.1, I've added the
> following workaround in Spyder (Spyder is monkey patching matplotlib anyway,
> to integrate mpl dockable figures in Spyder's GUI) -- other users may be
> interested to patch their matplotlib installation
> (matplotlib/backends/backend_qt4.py):
>
> # Add this before "FigureManagerQT" class
> class FigureWindow(QMainWindow):
>  def __init__(self):
>    super(FigureWindow, self).__init__()     def closeEvent(self,
> event):
>    super(FigureWindow, self).closeEvent(event)
>    if PYQT_VERSION_STR.startswith('4.6'):
>      self.emit(SIGNAL('destroyed()'))
> # Replace "QtGui.QMainWindow" by "FigureWindow" in "FigureManagerQT"'s
> constructor
>
> I hope this will be fixed in v4.6.2.
Me too. And thank you for posting the report and a workaround.
From: Fernando P. <fpe...@gm...> - 2009年12月31日 04:11:16
Attachments: mpl_qt4.diff
Howdy,
On Sat, Nov 7, 2009 at 12:30 PM, Darren Dale <dsd...@gm...> wrote:
> Me too. And thank you for posting the report and a workaround.
Quick question: would it be worth adding this monkeypatch to mpl
proper? Right now, the qt4 backend is effectively unusable out of the
box in distros like Karmic. Which is a bummer, because with the
ipython sitting on my laptop, one can now load 'pylab' at any time
during a session:
maqroll[scratch]> ip
Python 2.6.4 (r264:75706, Dec 7 2009, 18:45:15)
Type "copyright", "credits" or "license" for more information.
IPython 0.11.bzr.r1219 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object'. ?object also works, ?? prints more.
In [1]: import sys
In [2]: 'matplotlib' in sys.modules
Out[2]: False
In [3]: %pylab wx
Activating matplotlib with backend: WXAgg
 Welcome to pylab, a matplotlib-based Python environment.
 For more information, type 'help(pylab)'.
Switching IPython gui support to: wx True
In [4]: 'matplotlib' in sys.modules
Out[4]: True
In [5]: plot(sin(linspace(0,2*pi,200)))
Out[5]: [<matplotlib.lines.Line2D object at 0xae0dccc>]
This is starting to look very promising, but unfortunately:
- right now we don't have gui switching support for Qt3 at all in
ipython. Help is welcome, but I have no clue if it's easy/hard or
even needed much anymore...
- qt4 is unusable with the system's qt/pyqt...
So perhaps a local patch would be worth it, no? I can confirm that
with the attached patch, the new ipython support works:
In [1]: %pylab qt
Activating matplotlib with backend: Qt4Agg
 Welcome to pylab, a matplotlib-based Python environment.
 For more information, type 'help(pylab)'.
In [2]: run simpleplot.py
In [3]: close('all')
In [4]: run simpleplot.py
whereas before, I'd get the same nasty error mentioned above.
The patch now has no run-time impact (I modified Pierre's code a bit
so the check is done only once), but I'm not about to commit something
in the Qt backend without someone else's eyes, especially Darren's :)
Cheers,
f
From: Darren D. <dsd...@gm...> - 2009年12月31日 12:55:12
On Wed, Dec 30, 2009 at 11:11 PM, Fernando Perez <fpe...@gm...> wrote:
> Howdy,
>
> On Sat, Nov 7, 2009 at 12:30 PM, Darren Dale <dsd...@gm...> wrote:
>> Me too. And thank you for posting the report and a workaround.
>
> Quick question: would it be worth adding this monkeypatch to mpl
> proper? Right now, the qt4 backend is effectively unusable out of the
> box in distros like Karmic.
I have been resistant to committing this patch because (in my opinion)
mpl should not have to provide workarounds for bugs in package X on OS
Y, distribution Z. I think this particular issue was fixed when
PyQt4-4.6.2 was released. But its time to get practical, I suppose.
The patch looks fine, I just checked it into the trunk.
Darren
From: Fernando P. <fpe...@gm...> - 2009年12月31日 22:00:21
On Thu, Dec 31, 2009 at 4:54 AM, Darren Dale <dsd...@gm...> wrote:
> I have been resistant to committing this patch because (in my opinion)
> mpl should not have to provide workarounds for bugs in package X on OS
> Y, distribution Z. I think this particular issue was fixed when
> PyQt4-4.6.2 was released. But its time to get practical, I suppose.
> The patch looks fine, I just checked it into the trunk.
Thanks! As the zen goes, practicality beats purity :) I understand
your reluctance though, it's annoying to pepper mpl's code with this
kind of junk.
Happy New Year!
f
From: Pierre R. <co...@py...> - 2010年01月01日 09:47:04
2009年12月31日 Fernando Perez <fpe...@gm...>:
> On Thu, Dec 31, 2009 at 4:54 AM, Darren Dale <dsd...@gm...> wrote:
>> I have been resistant to committing this patch because (in my opinion)
>> mpl should not have to provide workarounds for bugs in package X on OS
>> Y, distribution Z. I think this particular issue was fixed when
>> PyQt4-4.6.2 was released. But its time to get practical, I suppose.
>> The patch looks fine, I just checked it into the trunk.
>
> Thanks! As the zen goes, practicality beats purity :) I understand
> your reluctance though, it's annoying to pepper mpl's code with this
> kind of junk.
>
> Happy New Year!
>
> f
>
I completely agree. If developers were all doing their "job" in time,
this should not be necessary and Darren's position would be perfectly
right and justified. However, especially on certain open-source
libraries, things are not moving as fast as they should. For example,
in Spyder I had to re-implement a console-oriented text editor widget
with Scintilla-like features because QScintilla's widget had a
performance issue with very long lines (which is almost undectectable
when using it as a simple text editor but it may slow down display
when using it as a console widget). This bug was fixed just a few days
after being reported but there has been no release since then (August
2009). So, to make it work, I had to do this big workaround until the
next release of QScintilla has spread on every platform (i.e. not
until a year I guess). In terms of code refactoring (or purity...),
this was not very satisfying but now Spyder works perfectly because I
stopped saying "it's not my fault, it's QScintilla's".
So even if I agree with Darren on the fact that libraries such as
matplotlib should not provide this kind of workaround, I also think
that -at some point- one has to get practical indeed!
Happy new year guys!
Cheers,
Pierre
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.
Thanks for helping keep SourceForge clean.
X





Briefly describe the problem (required):
Upload screenshot of ad (required):
Select a file, or drag & drop file here.
Screenshot instructions:

Click URL instructions:
Right-click on the ad, choose "Copy Link", then paste here →
(This may not be possible with some types of ads)

More information about our ad policies

Ad destination/click URL:

AltStyle によって変換されたページ (->オリジナル) /