bpo-43008: Make IDLE respect sys.excepthook (GH-24302)

Co-authored-by: Terry Jan Reedy <tjreedy@udel.edu>
diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py
index ec575c3..07e9a2b 100644
--- a/Lib/idlelib/run.py
+++ b/Lib/idlelib/run.py
@@ -16,6 +16,7 @@
 import threading
 import warnings
 
+import idlelib  # testing
 from idlelib import autocomplete  # AutoComplete, fetch_encodings
 from idlelib import calltip  # Calltip
 from idlelib import debugger_r  # start_debugger
@@ -542,14 +543,17 @@ class Executive:
 
     def __init__(self, rpchandler):
         self.rpchandler = rpchandler
-        self.locals = __main__.__dict__
-        self.calltip = calltip.Calltip()
-        self.autocomplete = autocomplete.AutoComplete()
+        if idlelib.testing is False:
+            self.locals = __main__.__dict__
+            self.calltip = calltip.Calltip()
+            self.autocomplete = autocomplete.AutoComplete()
+        else:
+            self.locals = {}
 
     def runcode(self, code):
         global interruptable
         try:
-            self.usr_exc_info = None
+            self.user_exc_info = None
             interruptable = True
             try:
                 exec(code, self.locals)
@@ -562,10 +566,17 @@ def runcode(self, code):
                     print('SystemExit: ' + str(ob), file=sys.stderr)
             # Return to the interactive prompt.
         except:
-            self.usr_exc_info = sys.exc_info()
+            self.user_exc_info = sys.exc_info()  # For testing, hook, viewer.
             if quitting:
                 exit()
-            print_exception()
+            if sys.excepthook is sys.__excepthook__:
+                print_exception()
+            else:
+                try:
+                    sys.excepthook(*self.user_exc_info)
+                except:
+                    self.user_exc_info = sys.exc_info()  # For testing.
+                    print_exception()
             jit = self.rpchandler.console.getvar("<<toggle-jit-stack-viewer>>")
             if jit:
                 self.rpchandler.interp.open_remote_stack_viewer()
@@ -590,8 +601,8 @@ def get_the_completion_list(self, what, mode):
         return self.autocomplete.fetch_completions(what, mode)
 
     def stackviewer(self, flist_oid=None):
-        if self.usr_exc_info:
-            typ, val, tb = self.usr_exc_info
+        if self.user_exc_info:
+            typ, val, tb = self.user_exc_info
         else:
             return None
         flist = None