From: Steve C. <ste...@ya...> - 2004-11-17 14:59:21
|
I've noticed a problem as follows: You run a GUI backend (GTK, GTKAgg etc) and want to save a figure. You select the toolbar save button and type in a .ps or .svg filename and select save. The GUI backend switches to the PS/SVG backend to save the file. If there is a problem saving the file, for example you do not have write permission to the directory, PS/SVG backends will kill your GUI application with sys.exit() I don't think failure to save a file should be a fatal error. Perhaps PS/SVG print_figure() could raise an exception for the GUI backend to catch so it can popup an error message and continue. Steve |
From: Jochen V. <vo...@se...> - 2004-11-18 16:44:12
|
Hello John, On Thu, Nov 18, 2004 at 10:24:57AM -0600, John Hunter wrote: > I suggest we rework the image backends to not define an error message > function at all, but simply to import and reuse the one from > backend_bases. This will make it easier to change the policy in a > single place. Secondly, an image backend should never call this > function, it should be reserved for the matlab interface simply to > insure a consistent interface between the various backends. Sorry, I am still not clear about this function. What is its purpose? When will it be called? > Thirdly, the image backends should verbose.report/report_error where > appropriate, and raise when indicated. GUI backends can catch these > exceptions and handle them how they want. This sounds fine for me. All the best, Jochen --=20 http://seehuhn.de/ |
From: John H. <jdh...@ac...> - 2004-11-18 17:00:16
|
>>>>> "Jochen" == Jochen Voss <vo...@se...> writes: Jochen> Sorry, I am still not clear about this function. What is Jochen> its purpose? When will it be called? Good question. In simple cases the matlab interface calls this function if illegal arguments are passed, eg if you call axis with the wrong signature if len(v) != 4: error_msg('v must contain [xmin xmax ymin ymax]') return This just displays the error and returns, non-fatal. In other functions, it does forwards the traceback message on to the error_msg function and then re-raises. This is done to prevent the gui from swallowing the traceback. But there is no coherent policy in the matlab interface in how error handling is done. Eg, in savefig, which calls print_figure for key in ('dpi', 'facecolor', 'edgecolor'): if not kwargs.has_key(key): kwargs[key] = rcParams['savefig.%s'%key] manager = get_current_fig_manager() manager.canvas.print_figure(*args, **kwargs) There is no try/except handling of print_figure. The leads to the question: which exceptions should the matlab interface handle when calling the backend? Do we do the extra work of defining the exception policy of backend functions and just catch these. Or do we catch all exceptions, forward the exception message to error_msg, and then re-raise the identical exception. The latter sounds reasonably coherent. Or do we start over with a new design? Wandering into murky waters here, is it possible for the GUIs simply to add an exception hook to hook the tracebacks into a GUI dialog box, and simply do away with error_msg all-together? I'm starting to like the sound of that. JDH |
From: Jochen V. <vo...@se...> - 2004-11-17 15:34:12
|
Hello Steve, On Wed, Nov 17, 2004 at 11:00:32PM +0800, Steve Chaplin wrote: > I don't think failure to save a file should be a fatal error. > Perhaps PS/SVG print_figure() could raise an exception for the GUI > backend to catch so it can popup an error message and continue. Even now you can probably (not tried) catch the SystemExit exception and prevent the program from aborting. Do you think raising SystemExit like raise SystemExit("error while writing file: permission denied") would be good enough. The GUI frontend could catch SystemExit, check whether the associated value is a string, and then display this string in an error message box. What do you think? Jochen --=20 http://seehuhn.de/ |
From: Fernando P. <Fer...@co...> - 2004-11-17 17:54:54
|
Jochen Voss schrieb: > Hello Steve, > > On Wed, Nov 17, 2004 at 11:00:32PM +0800, Steve Chaplin wrote: > >>I don't think failure to save a file should be a fatal error. >>Perhaps PS/SVG print_figure() could raise an exception for the GUI >>backend to catch so it can popup an error message and continue. > > Even now you can probably (not tried) catch the SystemExit > exception and prevent the program from aborting. > Do you think raising SystemExit like > > raise SystemExit("error while writing file: permission denied") > > would be good enough. The GUI frontend could catch SystemExit, > check whether the associated value is a string, and then display > this string in an error message box. > > What do you think? Bad design. Doing exception analysis based on string matching for the message is very brittle. A single change in capitalization of the message can break things down the road. It's _far_ better to either: 1. have the ps/svg backends do whatever cleanup they want, and then reraise the original exception unchanged 2. or simply make a matplotlib.SaveError exception which can be explicitly caught based on class matching, which is the preferred python way of doing this. Best, f |
From: Jochen V. <vo...@se...> - 2004-11-18 11:57:35
|
Hello, On Wed, Nov 17, 2004 at 10:54:49AM -0700, Fernando Perez wrote: > Bad design. Doing exception analysis based on string matching for the=20 > message is very brittle. A single change in capitalization of the messag= e=20 > can break things down the road. Sorry, maybe I was not clear enough. What I tried to suggest was: 1) GUI backends should catch the SystemExit exception from the PS backend, thus being able to continue running even if the backend aborts with an error. 2) GUI backends should in case that they caught a SystemExit exception notify the user that saving the figure as PostScript failed. If the exception is associated with an error message string, they could display this string to the user. > 1. have the ps/svg backends do whatever cleanup they want, and then rerai= se=20 > the original exception unchanged >=20 > 2. or simply make a matplotlib.SaveError exception which can be explicitl= y=20 > caught based on class matching, which is the preferred python way of doin= g=20 > this. Maybe. But how is any information except "the backend failed with error message ..." useful to the GUI? Would it act differently on an font-not-found condition then it would on a save-failed one? All the best, Jochen --=20 http://seehuhn.de/ |
From: Steve C. <ste...@ya...> - 2004-11-18 15:36:50
|
On Wed, 2004-11-17 at 10:54 -0700, Fernando Perez wrote: > Jochen Voss schrieb: > > Hello Steve, > > > > On Wed, Nov 17, 2004 at 11:00:32PM +0800, Steve Chaplin wrote: > > > >>I don't think failure to save a file should be a fatal error. > >>Perhaps PS/SVG print_figure() could raise an exception for the GUI > >>backend to catch so it can popup an error message and continue. > > > > Even now you can probably (not tried) catch the SystemExit > > exception and prevent the program from aborting. > > Do you think raising SystemExit like > > > > raise SystemExit("error while writing file: permission denied") > > > > would be good enough. The GUI frontend could catch SystemExit, > > check whether the associated value is a string, and then display > > this string in an error message box. > > > > What do you think? > > Bad design. Doing exception analysis based on string matching for the message > is very brittle. A single change in capitalization of the message can break > things down the road. > > It's _far_ better to either: > > 1. have the ps/svg backends do whatever cleanup they want, and then reraise > the original exception unchanged > > 2. or simply make a matplotlib.SaveError exception which can be explicitly > caught based on class matching, which is the preferred python way of doing this. > > Best, > > f At the moment the PS backend does try: fh = file(outfile, 'w') except IOError: error_msg_ps('Could not open %s for writing' % outfile) which translates into try: fh = file(outfile, 'w') except IOError: verbose.report_error('Error: Could not open %s for writing' % outfile) sys.exit() The backend does not do any cleanup after the exception, so I think it could be changed to just fh = file(outfile, 'w') allowing the exception terminate the program with the error message appearing at the end of the traceback. Then the GUI backends can then do from backend_svg import FigureCanvasSVG as FigureCanvas try: fc = self.switch_backends(FigureCanvas) fc.print_figure(filename, dpi, facecolor, edgecolor, orientation) except IOError, exc: error_msg("%s: %s" % (exc.filename, exc.strerror), parent=self) I tried this calling the SVG backend directly and by switching to the SVG backend from the GTK backend and it works OK. Steve |
From: Jochen V. <vo...@se...> - 2004-11-18 16:22:06
|
Hello Steve, On Thu, Nov 18, 2004 at 11:38:10PM +0800, Steve Chaplin wrote: > At the moment the PS backend does > try: > fh =3D file(outfile, 'w') > except IOError: > error_msg_ps('Could not open %s for writing' % outfile) >=20 > which translates into > try: > fh =3D file(outfile, 'w') > except IOError: > verbose.report_error('Error: Could not open %s for writing' % > outfile) > sys.exit() >=20 > The backend does not do any cleanup after the exception, so I think it > could be changed to just > fh =3D file(outfile, 'w') As I understood John, the plan is to report error messages via the verbose.report_error function. Where would this be called with the modified code (especially when there is no GUI backend active)? > allowing the exception terminate the program with the error message > appearing at the end of the traceback. This looks really ugly to me. But maybe it is the script author's responsibility to catch this if he cares about this. > Then the GUI backends can then do > from backend_svg import FigureCanvasSVG as FigureCanvas > try: > fc =3D self.switch_backends(FigureCanvas) > fc.print_figure(filename, dpi, facecolor, edgecolor, > orientation) > except IOError, exc: > error_msg("%s: %s" % (exc.filename, exc.strerror), parent=3Dself) What about other exceptions thrown by the backend? I see that passing the original exception to the caller is cleaner and I would be happy to change the PostScript backend to do this. The only question for me is: how and when is the "report_error" function to be used? All the best, Jochen --=20 http://seehuhn.de/ |
From: John H. <jdh...@ac...> - 2004-11-18 16:25:09
|
>>>>> "Steve" == Steve Chaplin <ste...@ya...> writes: Steve> I tried this calling the SVG backend directly and by Steve> switching to the SVG backend from the GTK backend and it Steve> works OK. This gets back to our previous unresolved discussion on error handling in the image backends. I think the way it is done now is a historical accident. In the olden days, pre matplotlib-0.50, there was no ability to switch backends, or to use an image backend within a GUI (eg gtkcairo, gtkagg). So the image backends were free-standing and their error handling didn't have much impact outside their own scope. Now they clearly do. The second design problem was that I preferred simple error messages rather than exceptions with tracebacks. This grew out of my experience with users of my GUIs who basically will not read a traceback - they appear to have blinders on. However, they will read a simple message like Could not save file blah, blah, blah. But as we are seeing, this approach (simple message, SystemExit) doesn't scale well and isn't appropriate when GUIs are calling image backends. I suggest we rework the image backends to not define an error message function at all, but simply to import and reuse the one from backend_bases. This will make it easier to change the policy in a single place. Secondly, an image backend should never call this function, it should be reserved for the matlab interface simply to insure a consistent interface between the various backends. Thirdly, the image backends should verbose.report/report_error where appropriate, and raise when indicated. GUI backends can catch these exceptions and handle them how they want. In the case at hand, it might be sensible for backend ps to catch an IO Error, report to verbose report_error, and then rethrow the error with the message. Something like try : save_ps(fname) except IOError, msg: verbose.report_error('Backend PS failed to save %s'%fname) raise IOError(msg) Thoughts? JDH |
From: Fernando P. <Fer...@co...> - 2004-11-18 18:57:30
|
John Hunter schrieb: > try : save_ps(fname) > except IOError, msg: > verbose.report_error('Backend PS failed to save %s'%fname) > raise IOError(msg) Just 'raise' is enough, python by default will re-raise the original exception untouched. I'll leave this discussion to you guys, I don't know the matplotlib code enough to contribute anything really useful. My only point is that reusing SystemExit for other purposes, with additional information encoded in the message, is IMHO a bad idea. There's a reason why exceptions make up a class hierarchy: this allows you to use classes for the flow control mechanisms, leaving the string messages simply as additional information mainly for the user. Since these messages are potentially locale-sensitive, and can change over time (spelling, capitalization, etc), it's just not a good idea to base code behaviour on them. Cheers, f |