wxDialog, raising exception in __init__

I have a somewhat larger dialog (selecting pictures) and in the constructor there could be an exception which I catch outside and destroy the dialog; now comes heap v stack: with a frame I get the address back and destroy, but with the dialog I don’t get the address right away and I use FindWindowByName; my question is whether there is a simpler way without using names?

I’m not sure I follow what it is you are having problems with or what you are asking. Can you share some of the relevant parts of your code? Or, better yet, create a minimal runnable sample application that demonstrates the problem?

I have made a little example: the console printout shows the correct identical behaviour, the instance is kept for performance and should go away in case of error…

import wx

class Gui(wx.Frame):
    def __init__(self):
        super().__init__(
            None,
            title='Demo Exception in __init__',
            style=wx.CAPTION | wx.CLOSE_BOX | wx.RESIZE_BORDER)

        panel = wx.Panel(self)
        vbox = wx.BoxSizer(wx.VERTICAL)

        #   Frame
        vbox.Add(
            wx.Button(panel, id=1, label='Frame'),
            0, wx.LEFT|wx.TOP|wx.RIGHT, 10)
        #   Dialog
        vbox.Add(
            wx.Button(panel, id=2, label='Dialog'),
            0, wx.LEFT|wx.TOP|wx.RIGHT, 10)

        panel.SetSizerAndFit(vbox)

        #   event bindings
        self.Bind(wx.EVT_CLOSE, self.on_quit)
        self.Bind(wx.EVT_BUTTON, self.event_button)

        self.sb = self.CreateStatusBar(1, style=wx.SB_FLAT)
        self.Show()

    def __del__(self):
        print(f'id {id(self)} {__class__}: __del__')

    def event_button(self, evt):
        if (b_id := evt.GetId()) == 1:
            if 'frame' not in vars(self):
                try:
                    inst = Frame(self)                # get instance of frame
                except:
                    return
                else:
                    self.frame = inst                   # save instance

        elif b_id == 2:
            if 'dialog' not in vars(self):
                try:                                            # get instance of dialog
                    inst = Dialog(self)
                except:
                #++++++++++++++++++++++++++++++++++
                    self.FindWindowByName('dialog', parent=self).Destroy()
                #++++++++++++++++++++++++++++++++++
                    return
            self.dialog = inst                              # save instance
            ret_code = inst.ShowModal()
            # do something according to ret_code

    def on_quit(self, evt):
        self.Destroy()

class Frame(wx.Frame):

    def __init__(self, parent):
        super().__init__(parent, title='Frame')
        print('Init frame')

        panel = wx.Panel(self)

        #   button
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        hbox.Add(wx.Button(panel, label='frame button'))

        panel.SetSizer(hbox)

        #   event bindings
        self.Bind(wx.EVT_CLOSE, self.on_quit)

        self.sb = self.CreateStatusBar(1, style=wx.SB_FLAT)

        error = True
        if error:
            parent.GetStatusBar().SetStatusText('Frame exception')
            self.Destroy()
            raise RuntimeError("Something bad happened")
        else:
            self.Show()

    def on_quit(self, evt):
        self.Destroy()

    def __del__(self):
        print(f'id {id(self)} {__class__}: __del__')

class Dialog(wx.Dialog):

    def __init__(self, parent):
        super().__init__(
            parent,
            title='Dialog',
            name='dialog')      # name is used for Destroy after init error
        print('Init dialouge')

        panel = wx.Panel(self)

        #   button
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        hbox.Add(wx.Button(panel, label='dialog button'))

        panel.SetSizer(hbox)

        #   event bindings
        self.Bind(wx.EVT_CLOSE, self.on_quit)

        error = True
        if error:
            parent.GetStatusBar().SetStatusText('Dialog exception')
            raise

    def __del__(self):
        print(f'id {id(self)} {__class__}: __del__')

    def on_quit(self, evt):
        self.Destroy()

class WxApp(wx.App):
    def __init__(self):
        try:
            super().__init__(filename=None)       #   with console
        except TypeError:
            print('Init error at wxApp')
        else:
            # set 'English' as language
            locale = wx.Locale()
            locale.Init(language=wx.LANGUAGE_ENGLISH)
            # self.Init()                                 # initialize the inspection tool
            frame = Gui()
            self.SetTopWindow(frame)
            self.MainLoop()

    def __del__(self):
        print(f'id {id(self)} {__class__}: __del__')

if __name__ == "__main__":
    WxApp()

It’s Markdown, so you just need to put code snippet blocks between ```…```

I’ll edit your first code sample message.

You should be able to have the dialog work the same as the frame and destroy itself when encountering the error. For top-level windows the destroy doesn’t actually happen until the next time the pending event queue is empty. So in either case the behavior can be the same.

You are right, it is absolutely symmetrical: something strange must have driven me; I think the ‘Show()’ inside and outside the constructor seduced me… thanks a lot