[v4,3/4] Rewrite "python" command exception handling

Message ID 20240227-py-simple-exc-v4-3-3341d342c126@adacore.com
State New
Headers
Series Fix DAP pause bug |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 warning Patch is already merged
linaro-tcwg-bot/tcwg_gdb_build--master-arm warning Patch is already merged

Commit Message

Tom Tromey Feb. 27, 2024, 2:45 p.m. UTC
  The "python" command (and the Python implementation of the gdb
"source" command) does not handle Python exceptions in the same way as
other gdb-facing Python code.  In particular, exceptions are turned
into a generic error rather than being routed through
gdbpy_handle_exception, which takes care of converting to 'quit' as
appropriate.

I think this was done this way because PyRun_SimpleFile and friends do
not propagate the Python exception -- they simply indicate that one
occurred.

This patch reimplements these functions to respect the general gdb
convention here.  As a bonus, some Windows-specific code can be
removed, as can the _execute_file function.

The bulk of this change is tweaking the test suite to match the new
way that exceptions are displayed.  These changes are largely
uninteresting.  However, it's worth pointing out the py-error.exp
change.  Here, the failure changes because the test changes the host
charset to something that isn't supported by Python.  This then
results in a weird error in the new setup.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31354
---
 gdb/doc/python.texi                               |   6 +-
 gdb/python/lib/gdb/__init__.py                    |  27 ------
 gdb/python/python.c                               | 109 +++++++++-------------
 gdb/testsuite/gdb.ada/tasks.exp                   |   8 +-
 gdb/testsuite/gdb.python/py-arch.exp              |   2 +-
 gdb/testsuite/gdb.python/py-block.exp             |   4 +-
 gdb/testsuite/gdb.python/py-breakpoint.exp        |  18 ++--
 gdb/testsuite/gdb.python/py-connection.exp        |   8 +-
 gdb/testsuite/gdb.python/py-disasm.exp            |  32 +++----
 gdb/testsuite/gdb.python/py-error.exp             |   9 +-
 gdb/testsuite/gdb.python/py-finish-breakpoint.exp |   2 +-
 gdb/testsuite/gdb.python/py-format-address.exp    |  28 +++---
 gdb/testsuite/gdb.python/py-format-string.exp     |   8 +-
 gdb/testsuite/gdb.python/py-frame.exp             |  18 ++--
 gdb/testsuite/gdb.python/py-inferior.exp          |  24 ++---
 gdb/testsuite/gdb.python/py-lazy-string.exp       |   6 +-
 gdb/testsuite/gdb.python/py-mi-cmd.exp            |  40 ++++----
 gdb/testsuite/gdb.python/py-missing-debug.exp     |  16 ++--
 gdb/testsuite/gdb.python/py-objfile.exp           |   2 +-
 gdb/testsuite/gdb.python/py-parameter.exp         |  14 +--
 gdb/testsuite/gdb.python/py-pp-registration.exp   |   2 +-
 gdb/testsuite/gdb.python/py-progspace-events.exp  |   2 +-
 gdb/testsuite/gdb.python/py-progspace.exp         |   8 +-
 gdb/testsuite/gdb.python/py-record-btrace.exp     |   4 +-
 gdb/testsuite/gdb.python/py-record-full.exp       |   4 +-
 gdb/testsuite/gdb.python/py-template.exp          |   2 +-
 gdb/testsuite/gdb.python/py-thrhandle.exp         |   2 +-
 gdb/testsuite/gdb.python/py-type.exp              |  20 ++--
 gdb/testsuite/gdb.python/py-unwind.exp            |  24 ++---
 gdb/testsuite/gdb.python/py-value.exp             |  36 +++----
 gdb/testsuite/gdb.python/python.exp               |  10 +-
 gdb/testsuite/gdb.python/tui-window-names.exp     |  16 ++--
 gdb/testsuite/gdb.python/tui-window.exp           |   2 +-
 gdb/testsuite/lib/gdb-python.exp                  |   2 +-
 34 files changed, 237 insertions(+), 278 deletions(-)
  

Comments

Tom de Vries Feb. 27, 2024, 4:03 p.m. UTC | #1
On 2/27/24 15:45, Tom Tromey wrote:
> The "python" command (and the Python implementation of the gdb
> "source" command) does not handle Python exceptions in the same way as
> other gdb-facing Python code.  In particular, exceptions are turned
> into a generic error rather than being routed through
> gdbpy_handle_exception, which takes care of converting to 'quit' as
> appropriate.
> 
> I think this was done this way because PyRun_SimpleFile and friends do
> not propagate the Python exception -- they simply indicate that one
> occurred.
> 
> This patch reimplements these functions to respect the general gdb
> convention here.  As a bonus, some Windows-specific code can be
> removed, as can the _execute_file function.
> 
> The bulk of this change is tweaking the test suite to match the new
> way that exceptions are displayed.  These changes are largely
> uninteresting.  However, it's worth pointing out the py-error.exp
> change.  Here, the failure changes because the test changes the host
> charset to something that isn't supported by Python.  This then
> results in a weird error in the new setup.
> 

Acked-By: Tom de Vries <tdevries@suse.de>

Thanks,
- Tom
  
Eli Zaretskii Feb. 27, 2024, 4:04 p.m. UTC | #2
> From: Tom Tromey <tromey@adacore.com>
> Date: Tue, 27 Feb 2024 07:45:51 -0700
> 
> The "python" command (and the Python implementation of the gdb
> "source" command) does not handle Python exceptions in the same way as
> other gdb-facing Python code.  In particular, exceptions are turned
> into a generic error rather than being routed through
> gdbpy_handle_exception, which takes care of converting to 'quit' as
> appropriate.
> 
> I think this was done this way because PyRun_SimpleFile and friends do
> not propagate the Python exception -- they simply indicate that one
> occurred.
> 
> This patch reimplements these functions to respect the general gdb
> convention here.  As a bonus, some Windows-specific code can be
> removed, as can the _execute_file function.
> 
> The bulk of this change is tweaking the test suite to match the new
> way that exceptions are displayed.  These changes are largely
> uninteresting.  However, it's worth pointing out the py-error.exp
> change.  Here, the failure changes because the test changes the host
> charset to something that isn't supported by Python.  This then
> results in a weird error in the new setup.
> 
> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31354
> ---
>  gdb/doc/python.texi                               |   6 +-
>  gdb/python/lib/gdb/__init__.py                    |  27 ------
>  gdb/python/python.c                               | 109 +++++++++-------------
>  gdb/testsuite/gdb.ada/tasks.exp                   |   8 +-
>  gdb/testsuite/gdb.python/py-arch.exp              |   2 +-
>  gdb/testsuite/gdb.python/py-block.exp             |   4 +-
>  gdb/testsuite/gdb.python/py-breakpoint.exp        |  18 ++--
>  gdb/testsuite/gdb.python/py-connection.exp        |   8 +-
>  gdb/testsuite/gdb.python/py-disasm.exp            |  32 +++----
>  gdb/testsuite/gdb.python/py-error.exp             |   9 +-
>  gdb/testsuite/gdb.python/py-finish-breakpoint.exp |   2 +-
>  gdb/testsuite/gdb.python/py-format-address.exp    |  28 +++---
>  gdb/testsuite/gdb.python/py-format-string.exp     |   8 +-
>  gdb/testsuite/gdb.python/py-frame.exp             |  18 ++--
>  gdb/testsuite/gdb.python/py-inferior.exp          |  24 ++---
>  gdb/testsuite/gdb.python/py-lazy-string.exp       |   6 +-
>  gdb/testsuite/gdb.python/py-mi-cmd.exp            |  40 ++++----
>  gdb/testsuite/gdb.python/py-missing-debug.exp     |  16 ++--
>  gdb/testsuite/gdb.python/py-objfile.exp           |   2 +-
>  gdb/testsuite/gdb.python/py-parameter.exp         |  14 +--
>  gdb/testsuite/gdb.python/py-pp-registration.exp   |   2 +-
>  gdb/testsuite/gdb.python/py-progspace-events.exp  |   2 +-
>  gdb/testsuite/gdb.python/py-progspace.exp         |   8 +-
>  gdb/testsuite/gdb.python/py-record-btrace.exp     |   4 +-
>  gdb/testsuite/gdb.python/py-record-full.exp       |   4 +-
>  gdb/testsuite/gdb.python/py-template.exp          |   2 +-
>  gdb/testsuite/gdb.python/py-thrhandle.exp         |   2 +-
>  gdb/testsuite/gdb.python/py-type.exp              |  20 ++--
>  gdb/testsuite/gdb.python/py-unwind.exp            |  24 ++---
>  gdb/testsuite/gdb.python/py-value.exp             |  36 +++----
>  gdb/testsuite/gdb.python/python.exp               |  10 +-
>  gdb/testsuite/gdb.python/tui-window-names.exp     |  16 ++--
>  gdb/testsuite/gdb.python/tui-window.exp           |   2 +-
>  gdb/testsuite/lib/gdb-python.exp                  |   2 +-
>  34 files changed, 237 insertions(+), 278 deletions(-)

Thanks, the documentation part is okay.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
  
Lancelot SIX March 7, 2024, 10 a.m. UTC | #3
On Tue, Feb 27, 2024 at 07:45:51AM -0700, Tom Tromey wrote:
> The "python" command (and the Python implementation of the gdb
> "source" command) does not handle Python exceptions in the same way as
> other gdb-facing Python code.  In particular, exceptions are turned
> into a generic error rather than being routed through
> gdbpy_handle_exception, which takes care of converting to 'quit' as
> appropriate.
> 
> I think this was done this way because PyRun_SimpleFile and friends do
> not propagate the Python exception -- they simply indicate that one
> occurred.
> 
> This patch reimplements these functions to respect the general gdb
> convention here.  As a bonus, some Windows-specific code can be
> removed, as can the _execute_file function.
> 
> The bulk of this change is tweaking the test suite to match the new
> way that exceptions are displayed.  These changes are largely
> uninteresting.  However, it's worth pointing out the py-error.exp
> change.  Here, the failure changes because the test changes the host
> charset to something that isn't supported by Python.  This then
> results in a weird error in the new setup.
> 
> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31354
> Reviewed-By: Eli Zaretskii <eliz@gnu.org>
> Acked-By: Tom de Vries <tdevries@suse.de>

Hi Tom,

Our internal testing caught a regression introduced by this change.

Let's say you have a python script like this in /tmp/foo.py:

    if __name__ == "__main__":
        print(__file__)

Before this patch, we would have:

    $ gdb -batch -quiet -x /tmp/foo.py
    /tmp/foo.py

With this patch, we now have:

    $ gdb -batch -quiet -x /tmp/foo.py
    Python Exception <class 'NameError'>: name '__file__' is not defined
    Error occurred in Python: name '__file__' is not defined

I have not looked into much details, but can try to have a look if you
don't have time.

Best,
Lancelot.
  
Tom Tromey March 8, 2024, 4:19 p.m. UTC | #4
>>>>> Lancelot SIX <lancelot.six@amd.com> writes:

> Our internal testing caught a regression introduced by this change.

Sorry about that.

Would you please file a bug for this?  You can assign it to me if you
want, or else I will.

Tom
  
Tom Tromey March 8, 2024, 7:24 p.m. UTC | #5
>> Our internal testing caught a regression introduced by this change.

Tom> Sorry about that.

Tom> Would you please file a bug for this?  You can assign it to me if you
Tom> want, or else I will.

Actually, I went ahead and fixed this today, so I don't think we'll need
a bug, unless we think the patch might not land on its own before gdb 15.

Tom
  

Patch

diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index 6b99a745c5d..4ae72716f56 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -721,9 +721,9 @@  When executing the @code{python} command, Python exceptions
 uncaught within the Python code are translated to calls to
 @value{GDBN} error-reporting mechanism.  If the command that called
 @code{python} does not handle the error, @value{GDBN} will
-terminate it and print an error message containing the Python
-exception name, the associated value, and the Python call stack
-backtrace at the point where the exception was raised.  Example:
+terminate it and print an error message.  Exactly what will be printed
+depends on @code{set python print-stack} (@pxref{Python Commands}).
+Example:
 
 @smallexample
 (@value{GDBP}) python print foo
diff --git a/gdb/python/lib/gdb/__init__.py b/gdb/python/lib/gdb/__init__.py
index ce8a6aae01e..cb3732e55f5 100644
--- a/gdb/python/lib/gdb/__init__.py
+++ b/gdb/python/lib/gdb/__init__.py
@@ -127,33 +127,6 @@  def _execute_unwinders(pending_frame):
     return None
 
 
-def _execute_file(filepath):
-    """This function is used to replace Python 2's PyRun_SimpleFile.
-
-    Loads and executes the given file.
-
-    We could use the runpy module, but its documentation says:
-    "Furthermore, any functions and classes defined by the executed code are
-    not guaranteed to work correctly after a runpy function has returned."
-    """
-    globals = sys.modules["__main__"].__dict__
-    set_file = False
-    # Set file (if not set) so that the imported file can use it (e.g. to
-    # access file-relative paths). This matches what PyRun_SimpleFile does.
-    if not hasattr(globals, "__file__"):
-        globals["__file__"] = filepath
-        set_file = True
-    try:
-        with open(filepath, "rb") as file:
-            # We pass globals also as locals to match what Python does
-            # in PyRun_SimpleFile.
-            compiled = compile(file.read(), filepath, "exec")
-            exec(compiled, globals, globals)
-    finally:
-        if set_file:
-            del globals["__file__"]
-
-
 # Convenience variable to GDB's python directory
 PYTHONDIR = os.path.dirname(os.path.dirname(__file__))
 
diff --git a/gdb/python/python.c b/gdb/python/python.c
index b2e8f244f85..8aa674c28d3 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -284,12 +284,14 @@  gdbpy_check_quit_flag (const struct extension_language_defn *extlang)
   return PyOS_InterruptOccurred ();
 }
 
-/* Evaluate a Python command like PyRun_SimpleString, but uses
-   Py_single_input which prints the result of expressions, and does
-   not automatically print the stack on errors.  */
+/* Evaluate a Python command like PyRun_SimpleString, but takes a
+   Python start symbol, and does not automatically print the stack on
+   errors.  FILENAME is used to set the file name in error
+   messages.  */
 
 static int
-eval_python_command (const char *command)
+eval_python_command (const char *command, int start_symbol,
+		     const char *filename = "<string>")
 {
   PyObject *m, *d;
 
@@ -300,8 +302,15 @@  eval_python_command (const char *command)
   d = PyModule_GetDict (m);
   if (d == NULL)
     return -1;
-  gdbpy_ref<> v (PyRun_StringFlags (command, Py_single_input, d, d, NULL));
-  if (v == NULL)
+
+  /* Use this API because it is in Python 3.2.  */
+  gdbpy_ref<> code (Py_CompileStringExFlags (command, filename, start_symbol,
+					     nullptr, -1));
+  if (code == nullptr)
+    return -1;
+
+  gdbpy_ref<> result (PyEval_EvalCode (code.get (), d, d));
+  if (result == nullptr)
     return -1;
 
   return 0;
@@ -324,7 +333,8 @@  python_interactive_command (const char *arg, int from_tty)
   if (arg && *arg)
     {
       std::string script = std::string (arg) + "\n";
-      err = eval_python_command (script.c_str ());
+      /* Py_single_input causes the result to be displayed.  */
+      err = eval_python_command (script.c_str (), Py_single_input);
     }
   else
     {
@@ -333,14 +343,12 @@  python_interactive_command (const char *arg, int from_tty)
     }
 
   if (err)
-    {
-      gdbpy_print_stack ();
-      error (_("Error while executing Python code."));
-    }
+    gdbpy_handle_exception ();
 }
 
-/* A wrapper around PyRun_SimpleFile.  FILE is the Python script to run
-   named FILENAME.
+/* Like PyRun_SimpleFile, but if there is an exception, it is not
+   automatically displayed.  FILE is the Python script to run named
+   FILENAME.
 
    On Windows hosts few users would build Python themselves (this is no
    trivial task on this platform), and thus use binaries built by
@@ -349,39 +357,13 @@  python_interactive_command (const char *arg, int from_tty)
    library.  Python, being built with VC, would use one version of the
    msvcr DLL (Eg. msvcr100.dll), while MinGW uses msvcrt.dll.
    A FILE * from one runtime does not necessarily operate correctly in
-   the other runtime.
+   the other runtime.  */
 
-   To work around this potential issue, we run code in Python to load
-   the script.  */
-
-static void
+static int
 python_run_simple_file (FILE *file, const char *filename)
 {
-#ifndef _WIN32
-
-  PyRun_SimpleFile (file, filename);
-
-#else /* _WIN32 */
-
-  /* Because we have a string for a filename, and are using Python to
-     open the file, we need to expand any tilde in the path first.  */
-  gdb::unique_xmalloc_ptr<char> full_path (tilde_expand (filename));
-
-  if (gdb_python_module == nullptr
-      || ! PyObject_HasAttrString (gdb_python_module, "_execute_file"))
-    error (_("Installation error: gdb._execute_file function is missing"));
-
-  gdbpy_ref<> return_value
-    (PyObject_CallMethod (gdb_python_module, "_execute_file", "s",
-			  full_path.get ()));
-  if (return_value == nullptr)
-    {
-      /* Use PyErr_PrintEx instead of gdbpy_print_stack to better match the
-	 behavior of the non-Windows codepath.  */
-      PyErr_PrintEx(0);
-    }
-
-#endif /* _WIN32 */
+  std::string contents = read_remainder_of_file (file);
+  return eval_python_command (contents.c_str (), Py_file_input, filename);
 }
 
 /* Given a command_line, return a command string suitable for passing
@@ -408,17 +390,15 @@  static void
 gdbpy_eval_from_control_command (const struct extension_language_defn *extlang,
 				 struct command_line *cmd)
 {
-  int ret;
-
   if (cmd->body_list_1 != nullptr)
     error (_("Invalid \"python\" block structure."));
 
   gdbpy_enter enter_py;
 
   std::string script = compute_python_string (cmd->body_list_0.get ());
-  ret = PyRun_SimpleString (script.c_str ());
-  if (ret)
-    error (_("Error while executing Python code."));
+  int ret = eval_python_command (script.c_str (), Py_file_input);
+  if (ret != 0)
+    gdbpy_handle_exception ();
 }
 
 /* Implementation of the gdb "python" command.  */
@@ -433,8 +413,9 @@  python_command (const char *arg, int from_tty)
   arg = skip_spaces (arg);
   if (arg && *arg)
     {
-      if (PyRun_SimpleString (arg))
-	error (_("Error while executing Python code."));
+      int ret = eval_python_command (arg, Py_file_input);
+      if (ret != 0)
+	gdbpy_handle_exception ();
     }
   else
     {
@@ -1050,7 +1031,9 @@  gdbpy_source_script (const struct extension_language_defn *extlang,
 		     FILE *file, const char *filename)
 {
   gdbpy_enter enter_py;
-  python_run_simple_file (file, filename);
+  int result = python_run_simple_file (file, filename);
+  if (result != 0)
+    gdbpy_handle_exception ();
 }
 
 
@@ -1682,7 +1665,9 @@  gdbpy_source_objfile_script (const struct extension_language_defn *extlang,
   scoped_restore restire_current_objfile
     = make_scoped_restore (&gdbpy_current_objfile, objfile);
 
-  python_run_simple_file (file, filename);
+  int result = python_run_simple_file (file, filename);
+  if (result != 0)
+    gdbpy_print_stack ();
 }
 
 /* Set the current objfile to OBJFILE and then execute SCRIPT
@@ -1703,7 +1688,9 @@  gdbpy_execute_objfile_script (const struct extension_language_defn *extlang,
   scoped_restore restire_current_objfile
     = make_scoped_restore (&gdbpy_current_objfile, objfile);
 
-  PyRun_SimpleString (script);
+  int ret = eval_python_command (script, Py_file_input);
+  if (ret != 0)
+    gdbpy_print_stack ();
 }
 
 /* Return the current Objfile, or None if there isn't one.  */
@@ -2361,21 +2348,15 @@  test_python ()
       {
 	CMD (output);
       }
-    catch (const gdb_exception &e)
+    catch (const gdb_exception_quit &e)
       {
 	saw_exception = true;
-	SELF_CHECK (e.reason == RETURN_ERROR);
-	SELF_CHECK (e.error == GENERIC_ERROR);
-	SELF_CHECK (*e.message == "Error while executing Python code.");
+	SELF_CHECK (e.reason == RETURN_QUIT);
+	SELF_CHECK (e.error == GDB_NO_ERROR);
+	SELF_CHECK (*e.message == "Quit");
       }
     SELF_CHECK (saw_exception);
-    std::string ref_output_0 ("Traceback (most recent call last):\n"
-			      "  File \"<string>\", line 0, in <module>\n"
-			      "KeyboardInterrupt\n");
-    std::string ref_output_1 ("Traceback (most recent call last):\n"
-			      "  File \"<string>\", line 1, in <module>\n"
-			      "KeyboardInterrupt\n");
-    SELF_CHECK (output == ref_output_0 || output == ref_output_1);
+    SELF_CHECK (output.empty ());
   }
 
 #undef CMD
diff --git a/gdb/testsuite/gdb.ada/tasks.exp b/gdb/testsuite/gdb.ada/tasks.exp
index dd03a2e4a96..6e588408c9d 100644
--- a/gdb/testsuite/gdb.ada/tasks.exp
+++ b/gdb/testsuite/gdb.ada/tasks.exp
@@ -98,15 +98,15 @@  if {[allow_python_tests]} {
     gdb_test "python print(bp.thread)" "None"
     gdb_test "python bp.thread = 1" \
 	[multi_line \
-	     "RuntimeError: Cannot set both task and thread attributes\\." \
-	     "Error while executing Python code\\."] \
+	     "RuntimeError.*: Cannot set both task and thread attributes\\." \
+	     "Error occurred in Python.*"] \
 	"try setting the thread, but expect an error"
     gdb_test_no_output "python bp.task = None"
     gdb_test_no_output "python bp.thread = 1"
     gdb_test "python bp.task = 3" \
 	[multi_line \
-	     "RuntimeError: Cannot set both task and thread attributes\\." \
-	     "Error while executing Python code\\."] \
+	     "RuntimeError.*: Cannot set both task and thread attributes\\." \
+	     "Error occurred in Python.*"] \
 	"try setting the task, but expect an error"
 
     # Reset the breakpoint to the state required for the rest of this
diff --git a/gdb/testsuite/gdb.python/py-arch.exp b/gdb/testsuite/gdb.python/py-arch.exp
index 1b0759a657d..3c58bf1281f 100644
--- a/gdb/testsuite/gdb.python/py-arch.exp
+++ b/gdb/testsuite/gdb.python/py-arch.exp
@@ -91,7 +91,7 @@  foreach size {0 1 2 3 4 8 16} {
 }
 
 gdb_test "python arch.integer_type(95)" \
-    ".*ValueError: no integer type of that size is available.*" \
+    ".*ValueError.* no integer type of that size is available.*" \
     "call integer_type with invalid size"
 
 # Test for gdb.architecture_names().  First we're going to grab the
diff --git a/gdb/testsuite/gdb.python/py-block.exp b/gdb/testsuite/gdb.python/py-block.exp
index 5e8fba43ea0..942611af305 100644
--- a/gdb/testsuite/gdb.python/py-block.exp
+++ b/gdb/testsuite/gdb.python/py-block.exp
@@ -44,9 +44,9 @@  gdb_test "python print (block.function)" "None" "first anonymous block"
 gdb_test "python print (block.start)" "${decimal}" "check start not None"
 gdb_test "python print (block.end)" "${decimal}" "check end not None"
 gdb_test "python print (block\['f'\].name == 'f')" "True" "check variable access"
-gdb_test "python print (block\['nonexistent'\])" ".*KeyError: 'nonexistent'.*" \
+gdb_test "python print (block\['nonexistent'\])" ".*KeyError.*: nonexistent.*" \
          "check nonexistent variable"
-gdb_test "python print (block\[42\])" ".*TypeError: Expected a string.*" \
+gdb_test "python print (block\[42\])" ".*TypeError.*: Expected a string.*" \
          "check non-string key"
 
 # Test global/static blocks
diff --git a/gdb/testsuite/gdb.python/py-breakpoint.exp b/gdb/testsuite/gdb.python/py-breakpoint.exp
index ef4c929fb15..c44477c326a 100644
--- a/gdb/testsuite/gdb.python/py-breakpoint.exp
+++ b/gdb/testsuite/gdb.python/py-breakpoint.exp
@@ -190,7 +190,7 @@  proc_with_prefix test_bkpt_deletion { } {
     gdb_py_test_silent_cmd  "python dp1.delete()" \
 	"Delete Breakpoint" 0
     gdb_test "python print (dp1.number)" \
-	"RuntimeError: Breakpoint 2 is invalid.*" \
+	"RuntimeError.*: Breakpoint 2 is invalid.*" \
 	"Check breakpoint invalidated"
     gdb_py_test_silent_cmd "python del_list = gdb.breakpoints()" \
 	"Get Breakpoint List" 0
@@ -275,7 +275,7 @@  proc_with_prefix test_bkpt_thread_and_inferior { } {
 	gdb_test "python print(bp.thread)" "1"
 	gdb_test "python print(bp.inferior)" "None"
 	gdb_test "python bp.inferior = 1" \
-	    "RuntimeError: Cannot have both 'thread' and 'inferior' conditions on a breakpoint.*"
+	    "RuntimeError.*: Cannot have both 'thread' and 'inferior' conditions on a breakpoint.*"
 	gdb_test_no_output "python bp.thread = None"
 	gdb_test_no_output "python bp.inferior = 1" \
 	    "set the inferior now the thread has been cleared"
@@ -289,7 +289,7 @@  proc_with_prefix test_bkpt_thread_and_inferior { } {
 	gdb_test "python print(bp.thread)" "None"
 	gdb_test "python print(bp.inferior)" "1"
 	gdb_test "python bp.thread = 1" \
-	    "RuntimeError: Cannot have both 'thread' and 'inferior' conditions on a breakpoint.*"
+	    "RuntimeError.*: Cannot have both 'thread' and 'inferior' conditions on a breakpoint.*"
 	gdb_test_no_output "python bp.inferior = None"
 	gdb_test_no_output "python bp.thread = 1" \
 	    "set the thread now the inferior has been cleared"
@@ -522,7 +522,7 @@  proc_with_prefix test_bkpt_eval_funcs { } {
 	"end" ""
 
     gdb_test "python eval_bp2.stop = stop_func"  \
-	"RuntimeError: Only one stop condition allowed.  There is currently a GDB.*" \
+	"RuntimeError.*: Only one stop condition allowed.  There is currently a GDB.*" \
 	"assign stop function to a breakpoint that has a condition"
 
     delete_breakpoints
@@ -589,7 +589,7 @@  proc_with_prefix test_bkpt_temporary { } {
 	".*$srcfile:$ibp_location.*"
     gdb_test "python print (ibp.count)" "1" \
 	"Check temporary stop callback executed before deletion."
-    gdb_test "python print (ibp.temporary)" "RuntimeError: Breakpoint 2 is invalid.*" \
+    gdb_test "python print (ibp.temporary)" "RuntimeError.*: Breakpoint 2 is invalid.*" \
 	"Check temporary breakpoint is deleted after being hit"
     gdb_test "info breakpoints" "No breakpoints, watchpoints, tracepoints, or catchpoints.*" \
 	"Check info breakpoints shows temporary breakpoint is deleted"
@@ -707,7 +707,7 @@  proc_with_prefix test_bkpt_explicit_loc {} {
 
     delete_breakpoints
     gdb_test "python bp1 = gdb.Breakpoint (line=bp1)" \
-	"RuntimeError: Line keyword should be an integer or a string.*" \
+	"RuntimeError.*: Line keyword should be an integer or a string.*" \
 	"set explicit breakpoint by invalid line type"
 
     delete_breakpoints
@@ -736,7 +736,7 @@  proc_with_prefix test_bkpt_explicit_loc {} {
 
     delete_breakpoints
     gdb_test "python bp1 = gdb.Breakpoint (source=\"$srcfile\")" \
-	"RuntimeError: Specifying a source must also include a line, label or function.*" \
+	"RuntimeError.*: Specifying a source must also include a line, label or function.*" \
 	"set invalid explicit breakpoint by source only"
 
     gdb_test "python bp1 = gdb.Breakpoint (source=\"foo.c\", line=\"5\")" \
@@ -859,8 +859,8 @@  proc_with_prefix test_catchpoints {} {
     # the python api.
     gdb_test "python gdb.Breakpoint (\"syscall\", type=gdb.BP_CATCHPOINT)" \
 	[multi_line \
-	     "gdb.error: BP_CATCHPOINT not supported" \
-	     "Error while executing Python code\\."] \
+	     "gdb.error.*: BP_CATCHPOINT not supported" \
+	     "Error occurred in Python:.*"] \
 	"create a catchpoint via the api"
 
     # Setup a catchpoint.
diff --git a/gdb/testsuite/gdb.python/py-connection.exp b/gdb/testsuite/gdb.python/py-connection.exp
index fa995f19d3d..ca78b37c4f1 100644
--- a/gdb/testsuite/gdb.python/py-connection.exp
+++ b/gdb/testsuite/gdb.python/py-connection.exp
@@ -65,10 +65,10 @@  gdb_test "python print(conn.is_valid())" "False" "is_valid returns False"
 # Now check that accessing properties of the invalid connection cases
 # an error.
 gdb_test "python print(conn.num)" \
-    "RuntimeError: Connection no longer exists\\.\r\n.*"
+    "RuntimeError.*: Connection no longer exists\\.\r\n.*"
 gdb_test "python print(conn.type)" \
-    "RuntimeError: Connection no longer exists\\.\r\n.*"
+    "RuntimeError.*: Connection no longer exists\\.\r\n.*"
 gdb_test "python print(conn.description)" \
-    "RuntimeError: Connection no longer exists\\.\r\n.*"
+    "RuntimeError.*: Connection no longer exists\\.\r\n.*"
 gdb_test "python print(conn.details)" \
-    "RuntimeError: Connection no longer exists\\.\r\n.*"
+    "RuntimeError.*: Connection no longer exists\\.\r\n.*"
diff --git a/gdb/testsuite/gdb.python/py-disasm.exp b/gdb/testsuite/gdb.python/py-disasm.exp
index 0458b33c5a9..7c6f972a7e7 100644
--- a/gdb/testsuite/gdb.python/py-disasm.exp
+++ b/gdb/testsuite/gdb.python/py-disasm.exp
@@ -164,16 +164,16 @@  foreach plan $test_plans {
 with_test_prefix "DisassemblerResult errors" {
     gdb_test "python gdb.disassembler.DisassemblerResult(0, 'abc')" \
 	[multi_line \
-	     "ValueError: Length must be greater than 0." \
-	     "Error while executing Python code."]
+	     "ValueError.*: Length must be greater than 0." \
+	     "Error occurred in Python.*"]
     gdb_test "python gdb.disassembler.DisassemblerResult(-1, 'abc')" \
 	[multi_line \
-	     "ValueError: Length must be greater than 0." \
-	     "Error while executing Python code."]
+	     "ValueError.*: Length must be greater than 0." \
+	     "Error occurred in Python.*"]
     gdb_test "python gdb.disassembler.DisassemblerResult(1, '')" \
 	[multi_line \
-	     "ValueError: String must not be empty." \
-	     "Error while executing Python code."]
+	     "ValueError.*: String must not be empty.*" \
+	     "Error occurred in Python.*"]
 }
 
 # Check that the architecture specific disassemblers can override the
@@ -255,8 +255,8 @@  with_test_prefix "Bad DisassembleInfo creation" {
     gdb_test "python print(my_info.is_valid())" "True"
     gdb_test "python gdb.disassembler.builtin_disassemble(my_info)" \
 	[multi_line \
-	     "RuntimeError: DisassembleInfo is no longer valid\\." \
-	     "Error while executing Python code\\."]
+	     "RuntimeError.*: DisassembleInfo is no longer valid\\." \
+	     "Error occurred in Python.*"]
 }
 
 # Some of the disassembler related types should not be sub-typed,
@@ -274,8 +274,8 @@  with_test_prefix "check inheritance" {
 	    "     pass" "" \
 	    "end" \
 	    [multi_line \
-		 "TypeError: type '${type_ptn}' is not an acceptable base type" \
-		 "Error while executing Python code\\."]
+		 "TypeError.*: type '${type_ptn}' is not an acceptable base type" \
+		 "Error occurred in Python.*"]
     }
 }
 
@@ -283,15 +283,15 @@  with_test_prefix "check inheritance" {
 # Test some error conditions when creating a DisassemblerResult object.
 gdb_test "python result = gdb.disassembler.DisassemblerResult()" \
     [multi_line \
-	 "TypeError: [missing_arg_pattern length 1]" \
-	 "Error while executing Python code\\."] \
+	 "TypeError.*: [missing_arg_pattern length 1]" \
+	 "Error occurred in Python.*"] \
     "try to create a DisassemblerResult without a length argument"
 
 foreach len {0 -1} {
     gdb_test "python result = gdb.disassembler.DisassemblerResult($len)" \
 	[multi_line \
-	     "ValueError: Length must be greater than 0\\." \
-	     "Error while executing Python code\\."] \
+	     "ValueError.*: Length must be greater than 0\\." \
+	     "Error occurred in Python.*"] \
 	"try to create a DisassemblerResult with length $len"
 }
 
@@ -300,7 +300,7 @@  foreach len {0 -1} {
 foreach type {DisassemblerTextPart DisassemblerAddressPart} {
     gdb_test "python result = gdb.disassembler.${type}()" \
 	[multi_line \
-	     "RuntimeError: Cannot create instances of DisassemblerPart\\." \
-	     "Error while executing Python code\\."] \
+	     "RuntimeError.*: Cannot create instances of DisassemblerPart\\." \
+	     "Error occurred in Python.*"] \
 	 "try to create an instance of ${type}"
 }
diff --git a/gdb/testsuite/gdb.python/py-error.exp b/gdb/testsuite/gdb.python/py-error.exp
index 58e8549453f..6eb9cc3d659 100644
--- a/gdb/testsuite/gdb.python/py-error.exp
+++ b/gdb/testsuite/gdb.python/py-error.exp
@@ -50,7 +50,12 @@  if {$test2 == ""} {
 set remote_python_file [gdb_remote_download host \
 			    ${srcdir}/${subdir}/${testfile}.py]
 
-# argc=LookupError: unknown encoding: IBM1047
-gdb_test "source $remote_python_file" "Traceback.*ClassName.*\r\nLookupError: unknown encoding: $charset" $test2
+# With the new way that "source" works, it isn't really possible for
+# this to fail "correctly".  Converting the filename to a Python
+# unicode object will fail -- and, mysteriously, without setting a
+# real exception.
+gdb_test "source $remote_python_file" \
+    "An error occurred in Python.*" \
+    $test2
 
 gdb_test "p 1" " = 1" "no delayed error"
diff --git a/gdb/testsuite/gdb.python/py-finish-breakpoint.exp b/gdb/testsuite/gdb.python/py-finish-breakpoint.exp
index 45e2630337f..905e6696322 100644
--- a/gdb/testsuite/gdb.python/py-finish-breakpoint.exp
+++ b/gdb/testsuite/gdb.python/py-finish-breakpoint.exp
@@ -81,7 +81,7 @@  with_test_prefix "normal conditions" {
 
     gdb_test "finish" "main.*" "return to main()"
     gdb_test "python MyFinishBreakpoint (None, gdb.selected_frame ())" \
-	"ValueError: \"FinishBreakpoint\" not meaningful in the outermost frame..*" \
+	"ValueError.*: \"FinishBreakpoint\" not meaningful in the outermost frame..*" \
 	"check FinishBP not allowed in main"
 }
 
diff --git a/gdb/testsuite/gdb.python/py-format-address.exp b/gdb/testsuite/gdb.python/py-format-address.exp
index 06654d98954..8e7cf47e03a 100644
--- a/gdb/testsuite/gdb.python/py-format-address.exp
+++ b/gdb/testsuite/gdb.python/py-format-address.exp
@@ -84,27 +84,27 @@  gdb_test "python print(\"Got: \" + gdb.format_address($main_addr, None, None))"
 # Now forget the architecture, this should fail.
 gdb_test "python print(\"Got: \" + gdb.format_address($main_addr, inf.progspace))" \
     [multi_line \
-	 "ValueError: The architecture and progspace arguments must both be supplied" \
-	 "Error while executing Python code\\."] \
+	 "ValueError.*: The architecture and progspace arguments must both be supplied" \
+	 "Error occurred in Python.*"] \
     "gdb.format_address passing program space only"
 
 gdb_test "python print(\"Got: \" + gdb.format_address($main_addr, inf.progspace, None))" \
     [multi_line \
-	 "ValueError: The architecture and progspace arguments must both be supplied" \
-	 "Error while executing Python code\\."] \
+	 "ValueError.*: The architecture and progspace arguments must both be supplied" \
+	 "Error occurred in Python.*"] \
     "gdb.format_address passing real program space, but architecture is None"
 
 # Now skip the program space argument.
 gdb_test "python print(\"Got: \" + gdb.format_address($main_addr, architecture=inf.architecture()))" \
     [multi_line \
-	 "ValueError: The architecture and progspace arguments must both be supplied" \
-	 "Error while executing Python code\\."] \
+	 "ValueError.*: The architecture and progspace arguments must both be supplied" \
+	 "Error occurred in Python.*"] \
     "gdb.format_address passing architecture only"
 
 gdb_test "python print(\"Got: \" + gdb.format_address($main_addr, None, inf.architecture()))" \
     [multi_line \
-	 "ValueError: The architecture and progspace arguments must both be supplied" \
-	 "Error while executing Python code\\."] \
+	 "ValueError.*: The architecture and progspace arguments must both be supplied" \
+	 "Error occurred in Python.*"] \
     "gdb.format_address passing real architecture, but progspace is None"
 
 # Now, before we add a second inferior, lets just check we can format
@@ -155,14 +155,14 @@  gdb_test "python print(\"Got: \" + gdb.format_address($bar_addr, inf2.progspace,
 # Try pasing incorrect object types for program space and architecture.
 gdb_test "python print(\"Got: \" + gdb.format_address($bar_addr, inf2.progspace, inf2.progspace))" \
     [multi_line \
-	 "TypeError: The architecture argument is not a gdb.Architecture object" \
-	 "Error while executing Python code\\."] \
+	 "TypeError.*: The architecture argument is not a gdb.Architecture object" \
+	 "Error occurred in Python.*"] \
     "gdb.format_address pass wrong object type for architecture"
 
 gdb_test "python print(\"Got: \" + gdb.format_address($bar_addr, inf2.architecture(), inf2.architecture()))" \
     [multi_line \
-	 "TypeError: The progspace argument is not a gdb.Progspace object" \
-	 "Error while executing Python code\\."] \
+	 "TypeError.*: The progspace argument is not a gdb.Progspace object" \
+	 "Error occurred in Python.*"] \
     "gdb.format_address pass wrong object type for progspace"
 
 # Now invalidate inferior 2's program space, and try using that.
@@ -171,6 +171,6 @@  gdb_test "python arch = inf2.architecture()"
 gdb_test "remove-inferior 2"
 gdb_test "python print(\"Got: \" + gdb.format_address($bar_addr, pspace, arch))" \
     [multi_line \
-	 "ValueError: The progspace argument is not valid" \
-	 "Error while executing Python code\\."] \
+	 "ValueError.*: The progspace argument is not valid" \
+	 "Error occurred in Python.*"] \
     "gdb.format_address called with an invalid program space"
diff --git a/gdb/testsuite/gdb.python/py-format-string.exp b/gdb/testsuite/gdb.python/py-format-string.exp
index cd434b8fd4b..0c70ad562c7 100644
--- a/gdb/testsuite/gdb.python/py-format-string.exp
+++ b/gdb/testsuite/gdb.python/py-format-string.exp
@@ -1102,22 +1102,22 @@  proc_with_prefix test_invalid_args {} {
   check_format_string \
     "a_point_t" \
     "12" \
-    "TypeError: format_string\\(\\) takes 0 positional arguments but 1 were given.*"
+    "TypeError.*: format_string\\(\\) takes 0 positional arguments but 1 were given.*"
 
   check_format_string \
     "a_point_t" \
     "invalid=True" \
-    "TypeError: 'invalid' is an invalid keyword argument for this function.*"
+    "TypeError.*: 'invalid' is an invalid keyword argument for this function.*"
 
   check_format_string \
     "a_point_t" \
     "raw='hello'" \
-    "TypeError: argument 1 must be bool, not str.*"
+    "TypeError.*: argument 1 must be bool, not str.*"
 
   check_format_string \
     "a_point_t" \
     "format='xd'" \
-    "ValueError: a single character is required.*"
+    "ValueError.*: a single character is required.*"
 }
 
 # Check the styling argument to format_string.  This function needs to
diff --git a/gdb/testsuite/gdb.python/py-frame.exp b/gdb/testsuite/gdb.python/py-frame.exp
index 110ddf24480..8f776eb08a5 100644
--- a/gdb/testsuite/gdb.python/py-frame.exp
+++ b/gdb/testsuite/gdb.python/py-frame.exp
@@ -77,25 +77,25 @@  gdb_test "python print (bf1.read_var(\"i\", sb).type)" "int" "test int i"
 # Test what happens when we provide a block of the wrong type.
 gdb_test "python print (bf1.read_var(\"i\", \"some_block\"))" \
     [multi_line \
-	 "TypeError: argument 2 must be gdb\\.Block, not str" \
-	 "Error while executing Python code\\."] \
+	 "TypeError.*: argument 2 must be gdb\\.Block, not str" \
+	 "Error occurred in Python.*"] \
     "check invalid block type error"
 gdb_test "python print (bf1.read_var(block = \"some_block\", variable = \"i\"))" \
     [multi_line \
-	 "TypeError: argument 2 must be gdb\\.Block, not str" \
-	 "Error while executing Python code\\."] \
+	 "TypeError.*: argument 2 must be gdb\\.Block, not str" \
+	 "Error occurred in Python.*"] \
     "check invalid block type error when named args are used"
 
 # Test what happens when we provide a variable of the wrong type.
 gdb_test "python print (bf1.read_var(None))" \
     [multi_line \
-	 "TypeError: argument 1 must be gdb\\.Symbol or str, not NoneType" \
-	 "Error while executing Python code\\."] \
+	 "TypeError.*: argument 1 must be gdb\\.Symbol or str, not NoneType" \
+	 "Error occurred in Python.*"] \
     "check read_var error when variable is None"
 gdb_test "python print (bf1.read_var(sb))" \
     [multi_line \
-	 "TypeError: argument 1 must be gdb\\.Symbol or str, not gdb\\.Block" \
-	 "Error while executing Python code\\."] \
+	 "TypeError.*: argument 1 must be gdb\\.Symbol or str, not gdb\\.Block" \
+	 "Error occurred in Python.*"] \
     "check read_var error when variable is a gdb.Block"
 
 gdb_breakpoint "f2"
@@ -141,7 +141,7 @@  gdb_test "python print ('result = %s' % f0.pc ())" " = \[0-9\]+" "test Frame.pc"
 gdb_test "python print ('result = %s' % (f0.older () == f1))" " = True" "test Frame.older"
 gdb_test "python print ('result = %s' % (f1.newer () == f0))" " = True" "test Frame.newer"
 gdb_test "python print ('result = %s' % f0.read_var ('variable_which_surely_doesnt_exist'))" \
-  "ValueError: Variable 'variable_which_surely_doesnt_exist' not found.*Error while executing Python code." \
+  "ValueError.*: Variable 'variable_which_surely_doesnt_exist' not found.*Error occurred in Python.*" \
   "test Frame.read_var - error"
 gdb_test "python print ('result = %s' % f0.read_var ('a'))" " = 1" "test Frame.read_var - success"
 
diff --git a/gdb/testsuite/gdb.python/py-inferior.exp b/gdb/testsuite/gdb.python/py-inferior.exp
index 2968e027812..c14f2d2796c 100644
--- a/gdb/testsuite/gdb.python/py-inferior.exp
+++ b/gdb/testsuite/gdb.python/py-inferior.exp
@@ -122,8 +122,8 @@  gdb_test "python print(worker_thread._user_attribute)" "123" \
     "read back user defined attribute"
 gdb_test "python print(main_thread._user_attribute)" \
     [multi_line \
-	 "AttributeError: 'gdb\\.InferiorThread' object has no attribute '_user_attribute'" \
-	 "Error while executing Python code\\."] \
+	 "AttributeError.*: 'gdb\\.InferiorThread' object has no attribute '_user_attribute'" \
+	 "Error occurred in Python.*"] \
     "attempt to read non-existent user defined attribute"
 
 # Proceed to the next test.
@@ -162,8 +162,8 @@  set num [add_inferior]
 # but that the first inferior does still have the attribute.
 gdb_test "python print(gdb.inferiors()\[1\]._user_attr)" \
     [multi_line \
-	 "AttributeError: 'gdb\\.Inferior' object has no attribute '_user_attr'" \
-	 "Error while executing Python code\\."] \
+	 "AttributeError.*: 'gdb\\.Inferior' object has no attribute '_user_attr'" \
+	 "Error occurred in Python.*"] \
     "check new inferior doesn't have user defined attribute"
 gdb_test "python print(gdb.inferiors()\[0\]._user_attr)" \
     "123" "read back user defined attribute again"
@@ -366,21 +366,21 @@  with_test_prefix "is_valid" {
     # Test that other properties and methods handle the removed inferior
     # correctly.
     gdb_test "python print (inf_list\[1\].num)" \
-	"RuntimeError: Inferior no longer exists.*"
+	"RuntimeError.*: Inferior no longer exists.*"
     gdb_test "python print (inf_list\[1\].connection_num)" \
-	"RuntimeError: Inferior no longer exists.*"
+	"RuntimeError.*: Inferior no longer exists.*"
     gdb_test "python print (inf_list\[1\].connection)" \
-	"RuntimeError: Inferior no longer exists.*"
+	"RuntimeError.*: Inferior no longer exists.*"
     gdb_test "python print (inf_list\[1\].pid)" \
-	"RuntimeError: Inferior no longer exists.*"
+	"RuntimeError.*: Inferior no longer exists.*"
     gdb_test "python print (inf_list\[1\].was_attached)" \
-	"RuntimeError: Inferior no longer exists.*"
+	"RuntimeError.*: Inferior no longer exists.*"
     gdb_test "python print (inf_list\[1\].progspace)" \
-	"RuntimeError: Inferior no longer exists.*"
+	"RuntimeError.*: Inferior no longer exists.*"
     gdb_test "python print (inf_list\[1\].threads ())" \
-	"RuntimeError: Inferior no longer exists.*"
+	"RuntimeError.*: Inferior no longer exists.*"
     gdb_test "python print (inf_list\[1\].thread_from_thread_handle (1))" \
-	"RuntimeError: Inferior no longer exists.*"
+	"RuntimeError.*: Inferior no longer exists.*"
 }
 
 # Test gdb.selected_inferior()
diff --git a/gdb/testsuite/gdb.python/py-lazy-string.exp b/gdb/testsuite/gdb.python/py-lazy-string.exp
index 8e7eca846b0..a00f47b1e2a 100644
--- a/gdb/testsuite/gdb.python/py-lazy-string.exp
+++ b/gdb/testsuite/gdb.python/py-lazy-string.exp
@@ -40,13 +40,13 @@  gdb_test "python print (nullstr.length)" "0" "null lazy string length"
 gdb_test "python print (nullstr.address)" "0" "null lazy string address"
 gdb_test "python print (nullstr.type)" "const char \\*" "null lazy string type"
 gdb_test "python print(nullstr.value())" \
-    "gdb.MemoryError: Cannot create a value from NULL.*Error while executing Python code." \
+    "gdb.MemoryError.*: Cannot create a value from NULL.*Error occurred in Python.*" \
     "create value from NULL"
 gdb_test "python print(null.lazy_string(length=3).value())" \
-    "gdb.MemoryError: Cannot create a lazy string with address 0x0, and a non-zero length.*Error while executing Python code." \
+    "gdb.MemoryError.*: Cannot create a lazy string with address 0x0, and a non-zero length.*Error occurred in Python.*" \
     "null lazy string with non-zero length"
 gdb_test "python print(null.lazy_string(length=-2))" \
-    "ValueError: Invalid length.*Error while executing Python code." \
+    "ValueError.*: Invalid length.*Error occurred in Python.*" \
     "bad length"
 
 foreach var_spec { { "ptr" "pointer" "const char \\*" -1 } \
diff --git a/gdb/testsuite/gdb.python/py-mi-cmd.exp b/gdb/testsuite/gdb.python/py-mi-cmd.exp
index d9fba23b39b..28c71cd75f3 100644
--- a/gdb/testsuite/gdb.python/py-mi-cmd.exp
+++ b/gdb/testsuite/gdb.python/py-mi-cmd.exp
@@ -70,7 +70,7 @@  mi_gdb_test "-pycmd bk2" \
 
 mi_gdb_test "-pycmd bk3" \
     [multi_line \
-	 "&\"TypeError: __repr__ returned non-string \\(type BadKey\\)..\"" \
+	 "&\"TypeError.*: __repr__ returned non-string \\(type BadKey\\)..\"" \
 	 "\\^error,msg=\"Error occurred in Python: __repr__ returned non-string \\(type BadKey\\)\""] \
     "-pycmd bk3"
 
@@ -156,23 +156,23 @@  mi_gdb_test "-pycmd-new int" \
     "-pycmd-new int - defined from MI"
 
 mi_gdb_test "python pycmd1('')" \
-    ".*&\"ValueError: MI command name is empty\\...\".*\\^error,msg=\"Error while executing Python code\\.\"" \
+    ".*&\"ValueError.*: MI command name is empty\\...\".*\\^error,msg=\"Error occurred in Python.*\"" \
     "empty MI command name"
 
 mi_gdb_test "python pycmd1('-')" \
     [multi_line \
 	 ".*" \
-	 "&\"ValueError: MI command name does not start with '-' followed by at least one letter or digit\\...\"" \
-	 "&\"Error while executing Python code\\...\"" \
-	 "\\^error,msg=\"Error while executing Python code\\.\""] \
+	 "&\"ValueError.*: MI command name does not start with '-' followed by at least one letter or digit\\...\"" \
+	 "&\"Error occurred in Python.*..\"" \
+	 "\\^error,msg=\"Error occurred in Python.*\""] \
     "invalid MI command name"
 
 mi_gdb_test "python pycmd1('-bad-character-@')" \
     [multi_line \
 	 ".*" \
-	 "&\"ValueError: MI command name contains invalid character: @\\...\"" \
-	 "&\"Error while executing Python code\\...\"" \
-	 "\\^error,msg=\"Error while executing Python code\\.\""] \
+	 "&\"ValueError.*: MI command name contains invalid character: @\\...\"" \
+	 "&\"Error occurred in Python.*..\"" \
+	 "\\^error,msg=\"Error occurred in Python.*\""] \
     "invalid character in MI command name"
 
 mi_gdb_test "python cmd=pycmd1('-abc')" \
@@ -258,9 +258,9 @@  mi_gdb_test "-aa" \
 mi_gdb_test "python aa.__init__('-bb', 'message three', 'zzz')" \
     [multi_line \
 	 ".*" \
-	 "&\"ValueError: can't reinitialize object with a different command name..\"" \
-	 "&\"Error while executing Python code\\...\"" \
-	 "\\^error,msg=\"Error while executing Python code\\.\""] \
+	 "&\"ValueError.*: can't reinitialize object with a different command name..\"" \
+	 "&\"Error occurred in Python.*..\"" \
+	 "\\^error,msg=\"Error occurred in Python.*\""] \
     "attempt to reinitialise aa variable to a new command name"
 
 mi_gdb_test "-aa" \
@@ -274,9 +274,9 @@  mi_gdb_test "python aa.installed = False" \
 mi_gdb_test "python aa.__init__('-bb', 'message three', 'zzz')" \
     [multi_line \
 	 ".*" \
-	 "&\"ValueError: can't reinitialize object with a different command name..\"" \
-	 "&\"Error while executing Python code\\...\"" \
-	 "\\^error,msg=\"Error while executing Python code\\.\""] \
+	 "&\"ValueError.*: can't reinitialize object with a different command name..\"" \
+	 "&\"Error occurred in Python.*..\"" \
+	 "\\^error,msg=\"Error occurred in Python.*\""] \
     "attempt to reinitialise aa variable to a new command name while uninstalled"
 
 mi_gdb_test "python aa.__init__('-aa', 'message three', 'zzz')" \
@@ -299,7 +299,7 @@  mi_gdb_test "python no_invoke('-no-invoke')" ".*\\^done" \
 mi_gdb_test "-no-invoke" \
     [multi_line \
 	 ".*" \
-	 "&\"AttributeError: 'no_invoke' object has no attribute 'invoke'..\"" \
+	 "&\"AttributeError.*: 'no_invoke' object has no attribute 'invoke'..\"" \
 	 "\\^error,msg=\"Error occurred in Python: 'no_invoke' object has no attribute 'invoke'\""] \
     "execute -no-invoke command, which is missing the invoke method"
 
@@ -312,14 +312,14 @@  mi_gdb_test "python delattr(no_invoke, 'invoke')" ".*\\^done"
 mi_gdb_test "-hello" \
     [multi_line \
 	 ".*" \
-	 "&\"AttributeError: 'no_invoke' object has no attribute 'invoke'..\"" \
+	 "&\"AttributeError.*: 'no_invoke' object has no attribute 'invoke'..\"" \
 	 "\\^error,msg=\"Error occurred in Python: 'no_invoke' object has no attribute 'invoke'\""] \
     "execute -hello command, that had its invoke method removed"
 mi_gdb_test "python cmd.invoke = 'string'" ".*\\^done"
 mi_gdb_test "-hello" \
     [multi_line \
 	 ".*" \
-	 "&\"TypeError: 'str' object is not callable..\"" \
+	 "&\"TypeError.*: 'str' object is not callable..\"" \
 	 "\\^error,msg=\"Error occurred in Python: 'str' object is not callable\""] \
     "execute command with invoke set to a string"
 
@@ -327,9 +327,9 @@  mi_gdb_test "-hello" \
 mi_gdb_test "python cmd = pycmd2('-data-disassemble')" \
     [multi_line \
 	 ".*" \
-	 "&\"RuntimeError: unable to add command, name is already in use..\"" \
-	 "&\"Error while executing Python code\\...\"" \
-	 "\\^error,msg=\"Error while executing Python code\\.\""] \
+	 "&\"RuntimeError.*: unable to add command, name is already in use..\"" \
+	 "&\"Error occurred in Python.*..\"" \
+	 "\\^error,msg=\"Error occurred in Python.*\""] \
     "try to register a command that replaces -data-disassemble"
 
 
diff --git a/gdb/testsuite/gdb.python/py-missing-debug.exp b/gdb/testsuite/gdb.python/py-missing-debug.exp
index 0aa4aaa010b..d1eef34c3f3 100644
--- a/gdb/testsuite/gdb.python/py-missing-debug.exp
+++ b/gdb/testsuite/gdb.python/py-missing-debug.exp
@@ -201,8 +201,8 @@  proc check_bad_name {name} {
     set name_re [string_to_regexp $name]
     set re \
 	[multi_line \
-	     "ValueError: invalid character '.' in handler name: $name_re" \
-	     "Error while executing Python code\\."]
+	     "ValueError.*: invalid character '.' in handler name: $name_re" \
+	     "Error occurred in Python.*"]
 
     gdb_test "python register(\"$name\")" $re \
 	"check that '$name' is not accepted"
@@ -442,13 +442,13 @@  with_test_prefix "check handler replacement" {
     # the same name.
     gdb_test "python gdb.missing_debug.register_handler(pspace, log_handler(\"Foo\"))" \
 	[multi_line \
-	     "RuntimeError: Handler Foo already exists\\." \
-	     "Error while executing Python code\\."]
+	     "RuntimeError.*: Handler Foo already exists\\." \
+	     "Error occurred in Python.*"]
 
     gdb_test "python gdb.missing_debug.register_handler(handler=log_handler(\"Foo\"), locus=pspace)" \
 	[multi_line \
-	     "RuntimeError: Handler Foo already exists\\." \
-	     "Error while executing Python code\\."]
+	     "RuntimeError.*: Handler Foo already exists\\." \
+	     "Error occurred in Python.*"]
 
     # And now try again, but this time with 'replace=True', we
     # shouldn't get an error in this case.
@@ -464,8 +464,8 @@  with_test_prefix "check handler replacement" {
 
     gdb_test "python gdb.missing_debug.register_handler(pspace, log_handler(\"Foo\"))" \
 	[multi_line \
-	     "RuntimeError: Handler Foo already exists\\." \
-	     "Error while executing Python code\\."] \
+	     "RuntimeError.*: Handler Foo already exists\\." \
+	     "Error occurred in Python.*"] \
 	"still get an error when handler is disabled"
 
     gdb_test_no_output \
diff --git a/gdb/testsuite/gdb.python/py-objfile.exp b/gdb/testsuite/gdb.python/py-objfile.exp
index 1ddc3ddab36..2f5b7752b43 100644
--- a/gdb/testsuite/gdb.python/py-objfile.exp
+++ b/gdb/testsuite/gdb.python/py-objfile.exp
@@ -30,7 +30,7 @@  if {![runto_main]} {
     return 0
 }
 
-set python_error_text "Error while executing Python code\\."
+set python_error_text "Error occurred in Python.*"
 
 gdb_py_test_silent_cmd "python sym = gdb.lookup_symbol(\"some_var\")" \
     "Find a symbol in objfile" 1
diff --git a/gdb/testsuite/gdb.python/py-parameter.exp b/gdb/testsuite/gdb.python/py-parameter.exp
index 94702f42816..de524f49ad6 100644
--- a/gdb/testsuite/gdb.python/py-parameter.exp
+++ b/gdb/testsuite/gdb.python/py-parameter.exp
@@ -342,7 +342,7 @@  proc_with_prefix test_gdb_parameter { } {
     } {
 	clean_restart
 
-	set param_range_error ".*gdb.error: integer -1 out of range.*"
+	set param_range_error ".*gdb.error.*: integer -1 out of range.*"
 	switch -- $param {
 	    "listsize" {
 		set param_get_zero None
@@ -438,8 +438,8 @@  proc_with_prefix test_integer_parameter { } {
 	    "test_param_$kind = TestNodocParam ('test-$kind')" "" \
 	    "end"
 
-	set param_range_error "RuntimeError: Range exceeded.*"
-	set param_integer_error "RuntimeError: The value must be integer.*"
+	set param_range_error "RuntimeError.*: Range exceeded.*"
+	set param_integer_error "RuntimeError.*: The value must be integer.*"
 	switch -- $kind {
 	    PARAM_UINTEGER {
 		set param_get_zero None
@@ -610,13 +610,13 @@  proc_with_prefix test_ambiguous_parameter {} {
 
     # Test ambiguous names.
     gdb_test "python print(gdb.parameter('test-ambiguou'))" \
-	"Parameter .* is ambiguous.*Error while executing Python code."
+	"Parameter .* is ambiguous.*Error occurred in Python.*"
     gdb_test "python print(gdb.parameter('test-ambiguous-'))" \
-	"Parameter .* is ambiguous.*Error while executing Python code."
+	"Parameter .* is ambiguous.*Error occurred in Python.*"
     gdb_test "python print(gdb.parameter('test-ambiguous-v'))" \
-	"Parameter .* is ambiguous.*Error while executing Python code."
+	"Parameter .* is ambiguous.*Error occurred in Python.*"
     gdb_test "python print(gdb.parameter('test-ambiguous-value-1a'))" \
-	"Could not find parameter.*Error while executing Python code."
+	"Could not find parameter.*Error occurred in Python.*"
 }
 
 test_directories
diff --git a/gdb/testsuite/gdb.python/py-pp-registration.exp b/gdb/testsuite/gdb.python/py-pp-registration.exp
index 68599d67a16..4bfdf5e5612 100644
--- a/gdb/testsuite/gdb.python/py-pp-registration.exp
+++ b/gdb/testsuite/gdb.python/py-pp-registration.exp
@@ -102,7 +102,7 @@  with_test_prefix "replace" {
     gdb_test_no_output "py gdb.printing.register_pretty_printer(gdb, lookup_function_lookup_test)"
     gdb_test_no_output "py gdb.printing.register_pretty_printer(progspace, my_pretty_printer1)"
     gdb_test "py gdb.printing.register_pretty_printer(progspace, my_pretty_printer2, replace=False)" \
-	"RuntimeError: pretty-printer already registered: pp-test\r\nError while executing Python code."
+	"RuntimeError.*: pretty-printer already registered: pp-test\r\nError occurred in Python.*"
 
     with_test_prefix "test printers 1" {
 	test_printers "s1"
diff --git a/gdb/testsuite/gdb.python/py-progspace-events.exp b/gdb/testsuite/gdb.python/py-progspace-events.exp
index 47a9985317e..95e4ca8da0b 100644
--- a/gdb/testsuite/gdb.python/py-progspace-events.exp
+++ b/gdb/testsuite/gdb.python/py-progspace-events.exp
@@ -107,7 +107,7 @@  set warning_msg \
 
 gdb_test "step" \
     [multi_line \
-	 "^FreeProgspaceEvent: <gdb.Progspace object at $hex>(?:\r\n$warning_msg)*" \
+	 "^FreeProgspaceEvent.*: <gdb.Progspace object at $hex>(?:\r\n$warning_msg)*" \
 	 "do_parent_stuff \\(\\) at \[^\r\n\]+" \
 	 "$decimal\\s+\[^\r\n\]+"]
 
diff --git a/gdb/testsuite/gdb.python/py-progspace.exp b/gdb/testsuite/gdb.python/py-progspace.exp
index f76e1f9359a..0ae5b5673d8 100644
--- a/gdb/testsuite/gdb.python/py-progspace.exp
+++ b/gdb/testsuite/gdb.python/py-progspace.exp
@@ -55,8 +55,8 @@  gdb_test "python print (progspace.random_attribute)" "42" \
 
 # Check that we can't create new (invalid) gdb.Progspace objects.
 gdb_test "python gdb.Progspace()" \
-    [multi_line "TypeError: cannot create 'gdb.Progspace' instances" \
-	 "Error while executing Python code\\."] \
+    [multi_line "TypeError.*: cannot create 'gdb.Progspace' instances" \
+	 "Error occurred in Python.*"] \
     "check for error when calling gdb.Progspace() directly"
 
 if {![runto_main]} {
@@ -111,7 +111,7 @@  gdb_py_test_silent_cmd "python progspace2 = gdb.current_progspace()" \
 gdb_test "inferior 1" "Switching to inferior 1.*"
 gdb_test_no_output "remove-inferiors 2"
 gdb_test "python print (progspace2.objfiles ())" \
-    "RuntimeError: Program space no longer exists.*"
+    "RuntimeError.*: Program space no longer exists.*"
 
 gdb_test "python print (progspace2.symbol_file)" \
-    "RuntimeError: Program space no longer exists.*"
+    "RuntimeError.*: Program space no longer exists.*"
diff --git a/gdb/testsuite/gdb.python/py-record-btrace.exp b/gdb/testsuite/gdb.python/py-record-btrace.exp
index 71ff52ed137..fba0b98f794 100644
--- a/gdb/testsuite/gdb.python/py-record-btrace.exp
+++ b/gdb/testsuite/gdb.python/py-record-btrace.exp
@@ -34,12 +34,12 @@  with_test_prefix "no or double record" {
 
     gdb_test_no_output "python gdb.start_recording(\"btrace\")"
     gdb_test "python gdb.start_recording(\"btrace\")" \
-	".*gdb\.error: The process is already being recorded\..*" \
+	".*gdb\.error.*: The process is already being recorded\..*" \
 	"already recording"
 
     gdb_test_no_output "python gdb.stop_recording()" "first"
     gdb_test "python gdb.stop_recording()" \
-	".*gdb\.error: No recording is currently active\..*" "second"
+	".*gdb\.error.*: No recording is currently active\..*" "second"
 }
 
 with_test_prefix "preopened record btrace" {
diff --git a/gdb/testsuite/gdb.python/py-record-full.exp b/gdb/testsuite/gdb.python/py-record-full.exp
index 19497fb3cd1..da38d1cab6b 100644
--- a/gdb/testsuite/gdb.python/py-record-full.exp
+++ b/gdb/testsuite/gdb.python/py-record-full.exp
@@ -34,12 +34,12 @@  with_test_prefix "no or double record" {
 
     gdb_test_no_output "python gdb.start_recording(\"full\")"
     gdb_test "python gdb.start_recording(\"full\")" \
-	".*gdb\.error: The process is already being recorded\..*" \
+	".*gdb\.error.*: The process is already being recorded\..*" \
 	"already recording"
 
     gdb_test_no_output "python gdb.stop_recording()" "first"
     gdb_test "python gdb.stop_recording()" \
-	".*gdb\.error: No recording is currently active\..*" "second"
+	".*gdb\.error.*: No recording is currently active\..*" "second"
 }
 
 with_test_prefix "preopened record full" {
diff --git a/gdb/testsuite/gdb.python/py-template.exp b/gdb/testsuite/gdb.python/py-template.exp
index fbb745506e2..bba80e3b870 100644
--- a/gdb/testsuite/gdb.python/py-template.exp
+++ b/gdb/testsuite/gdb.python/py-template.exp
@@ -50,7 +50,7 @@  proc test_template_arg {exefile type} {
     gdb_test "python print (foo.type.template_argument(0))" $t $type
 
     gdb_test "python print(foo.type.template_argument(-1))" \
-	"Template argument number must be non-negative\r\nError while executing Python code." \
+	"Template argument number must be non-negative\r\nError occurred in Python.*" \
 	"negative template argument number in template test of $type"
 }
 
diff --git a/gdb/testsuite/gdb.python/py-thrhandle.exp b/gdb/testsuite/gdb.python/py-thrhandle.exp
index 60399774b1b..939f0a86f48 100644
--- a/gdb/testsuite/gdb.python/py-thrhandle.exp
+++ b/gdb/testsuite/gdb.python/py-thrhandle.exp
@@ -90,7 +90,7 @@  gdb_test "python print(gdb.selected_inferior().thread_from_handle(gdb.parse_and_
 # We should see an exception when passing an object of the wrong type.
 
 gdb_test "python print(gdb.selected_inferior().thread_from_handle(gdb.lookup_symbol('main')))" \
-         ".*TypeError: Argument 'handle' must be a thread handle object.*" \
+         ".*TypeError.*: Argument 'handle' must be a thread handle object.*" \
 	 "TypeError when passing a symbol object to thread_from_handle"
 
 # We should see an exception when passing too large of an object.
diff --git a/gdb/testsuite/gdb.python/py-type.exp b/gdb/testsuite/gdb.python/py-type.exp
index 1e9e7152f78..74e123441c4 100644
--- a/gdb/testsuite/gdb.python/py-type.exp
+++ b/gdb/testsuite/gdb.python/py-type.exp
@@ -121,10 +121,10 @@  proc test_fields {lang} {
     gdb_test "python print (not not st.type)" "True" "check conversion to bool"
 
     # Test rejection of mapping operations on scalar types
-    gdb_test "python print (len (st.type\['a'\].type))" "TypeError: Type is not a structure, union, enum, or function type.*"
-    gdb_test "python print (st.type\['a'\].type.has_key ('x'))" "TypeError: Type is not a structure, union, enum, or function type.*"
-    gdb_test "python print (st.type\['a'\].type\['x'\])" "TypeError: Type is not a structure, union, enum, or function type.*"
-    gdb_test "python print (st.type\['a'\].type.keys ())" "TypeError: Type is not a structure, union, enum, or function type.*"
+    gdb_test "python print (len (st.type\['a'\].type))" "TypeError.*: Type is not a structure, union, enum, or function type.*"
+    gdb_test "python print (st.type\['a'\].type.has_key ('x'))" "TypeError.*: Type is not a structure, union, enum, or function type.*"
+    gdb_test "python print (st.type\['a'\].type\['x'\])" "TypeError.*: Type is not a structure, union, enum, or function type.*"
+    gdb_test "python print (st.type\['a'\].type.keys ())" "TypeError.*: Type is not a structure, union, enum, or function type.*"
 
     # Test conversion to bool on scalar types
     gdb_test "python print (not not st.type\['a'\].type)" "True"
@@ -167,7 +167,7 @@  proc test_fields {lang} {
     gdb_test "python print (gdb.parse_and_eval ('a_function').type.fields ()\[1\].type)" "char"
 
     # Test calling `fields` on a non-aggregate type.
-    gdb_test "python gdb.lookup_type('int').fields()" "TypeError: Type is not a structure, union, enum, or function type.*"
+    gdb_test "python gdb.lookup_type('int').fields()" "TypeError.*: Type is not a structure, union, enum, or function type.*"
   }
 }
 
@@ -224,7 +224,7 @@  proc test_range {} {
       # Test where a range does not exist.
       gdb_py_test_silent_cmd "print (st)" "print value (st)" 1
       gdb_py_test_silent_cmd "python st = gdb.history (0)" "get value (st) from history" 1
-      gdb_test "python print (st.type.range())" "RuntimeError: This type does not have a range.*" "check range for non ranged type."
+      gdb_test "python print (st.type.range())" "RuntimeError.*: This type does not have a range.*" "check range for non ranged type."
     }
   }
 }
@@ -264,7 +264,7 @@  proc test_template {} {
 proc test_is_signed {lang} {
     if {$lang == "c++"} {
 	gdb_test "python print(gdb.parse_and_eval ('c').type.is_signed)"  \
-	"ValueError: Type must be a scalar type.*"
+	"ValueError.*: Type must be a scalar type.*"
 	gdb_test "python print(gdb.parse_and_eval ('&c').type.is_signed == False)" "True"
     }
 
@@ -274,13 +274,13 @@  proc test_is_signed {lang} {
 
     gdb_test "python print(gdb.parse_and_eval ('ss.x').type.is_signed == True)" "True"
     gdb_test "python print(gdb.parse_and_eval ('ss').type.is_signed)" \
-	"ValueError: Type must be a scalar type.*"
+	"ValueError.*: Type must be a scalar type.*"
     gdb_test "python print(gdb.parse_and_eval ('uu').type.is_signed)"  \
-	"ValueError: Type must be a scalar type.*"
+	"ValueError.*: Type must be a scalar type.*"
     gdb_test "python print(gdb.parse_and_eval ('uu.i').type.is_signed == True)" "True"
     gdb_test "python print(gdb.parse_and_eval ('uu.f').type.is_signed == True)" "True"
     gdb_test "python print(gdb.parse_and_eval ('uu.a').type.is_signed)"  \
-	"ValueError: Type must be a scalar type.*"
+	"ValueError.*: Type must be a scalar type.*"
 
     gdb_test "python print(gdb.parse_and_eval ('&ss.x').type.is_signed == False)" "True"
     gdb_test "python print(gdb.parse_and_eval ('&uu').type.is_signed == False)" "True"
diff --git a/gdb/testsuite/gdb.python/py-unwind.exp b/gdb/testsuite/gdb.python/py-unwind.exp
index 1f88be0ac97..d5efc0216cf 100644
--- a/gdb/testsuite/gdb.python/py-unwind.exp
+++ b/gdb/testsuite/gdb.python/py-unwind.exp
@@ -97,8 +97,8 @@  check_for_fixed_backtrace "check backtrace after flush"
 # output to be sure.
 gdb_test "python global_test_unwinder.enabled = \"off\"" \
     [multi_line \
-	 "TypeError: incorrect type for enabled attribute: <class 'str'>" \
-	 "Error while executing Python code\\."]
+	 "TypeError.*: incorrect type for enabled attribute: <class 'str'>" \
+	 "Error occurred in Python.*"]
 check_info_unwinder "info unwinder after failed disable" on
 
 # While we're doing silly stuff, lets try to change the name of this
@@ -109,8 +109,8 @@  set pattern_1 "can't set attribute(?: 'name')?"
 set pattern_2 "property 'name' of 'TestUnwinder' object has no setter"
 gdb_test "python global_test_unwinder.name = \"foo\"" \
     [multi_line \
-	 "AttributeError: (?:${pattern_1}|${pattern_2})" \
-	 "Error while executing Python code\\."]
+	 "AttributeError.*: (?:${pattern_1}|${pattern_2})" \
+	 "Error occurred in Python.*"]
 check_info_unwinder "info unwinder after failed name change" on
 
 # Now actually disable the unwinder by manually adjusting the
@@ -149,8 +149,8 @@  gdb_test "python print(read_register_error)" "Bad register" \
 # Try to create an unwinder object with a non-string name.
 gdb_test "python obj = simple_unwinder(True)" \
     [multi_line \
-	 "TypeError: incorrect type for name: <class 'bool'>" \
-	 "Error while executing Python code\\."]
+	 "TypeError.*: incorrect type for name: <class 'bool'>" \
+	 "Error occurred in Python.*"]
 
 # Now register the simple_unwinder with a valid name, and use the
 # unwinder to capture a PendingFrame object.
@@ -195,8 +195,8 @@  foreach cmd {"pf.read_register(\"pc\")" \
 		 "pf.function()" } {
     gdb_test "python $cmd" \
 	[multi_line \
-	     "ValueError: gdb\\.PendingFrame is invalid\\." \
-	     "Error while executing Python code\\."]
+	     "ValueError.*: gdb\\.PendingFrame is invalid\\." \
+	     "Error occurred in Python.*"]
 }
 
 # Turn on the useful unwinder so we have the full backtrace again, and
@@ -265,11 +265,11 @@  gdb_test_multiline "Sub-class gdb.UnwindInfo " \
     "    pass" "" \
     "end" \
     [multi_line \
-	 "TypeError: type 'gdb\\.UnwindInfo' is not an acceptable base type" \
-	 "Error while executing Python code\\."]
+	 "TypeError.*: type 'gdb\\.UnwindInfo' is not an acceptable base type" \
+	 "Error occurred in Python.*"]
 
 # Check we can't directly instantiate a gdb.UnwindInfo.
 gdb_test "python uw = gdb.UnwindInfo()" \
     [multi_line \
-     "TypeError: cannot create 'gdb\\.UnwindInfo' instances" \
-     "Error while executing Python code\\."]
+     "TypeError.*: cannot create 'gdb\\.UnwindInfo' instances" \
+     "Error occurred in Python.*"]
diff --git a/gdb/testsuite/gdb.python/py-value.exp b/gdb/testsuite/gdb.python/py-value.exp
index ff6b8b931f4..aa674e8aa0d 100644
--- a/gdb/testsuite/gdb.python/py-value.exp
+++ b/gdb/testsuite/gdb.python/py-value.exp
@@ -159,7 +159,7 @@  proc test_value_numeric_ops {} {
   }
 
   gdb_test_multiple "python print ('result = ' + str(i+gdb.Value('foo')))" "catch throw of GDB error" {
-      -re "Traceback.*$gdb_prompt $"  {pass "catch throw of GDB error"}
+      -re "Error occurred in Python.*$gdb_prompt $"  {pass "catch throw of GDB error"}
       -re "result = .*$gdb_prompt $"  {fail "catch throw of GDB error"}
       -re "$gdb_prompt $"	      {fail "catch throw of GDB error"}
   }
@@ -270,7 +270,7 @@  proc test_value_in_inferior {} {
   if {$can_read_0} {
     untested $test
   } else {
-    gdb_test "python print (gdb.parse_and_eval('*(int*)0'))" "gdb.MemoryError: Cannot access memory at address 0x0.*" $test
+    gdb_test "python print (gdb.parse_and_eval('*(int*)0'))" "gdb.MemoryError.*: Cannot access memory at address 0x0.*" $test
   }
 
   # Test Python lazy value handling
@@ -281,10 +281,10 @@  proc test_value_in_inferior {} {
     gdb_test "python inval = gdb.parse_and_eval('*(int*)0')"
     gdb_test "python print (inval.is_lazy)" "True"
     gdb_test "python inval2 = inval+1" \
-	"gdb.MemoryError: Cannot access memory at address 0x0.*" \
+	"gdb.MemoryError.*: Cannot access memory at address 0x0.*" \
 	"$test, first test"
     gdb_test "python inval.fetch_lazy ()" \
-	"gdb.MemoryError: Cannot access memory at address 0x0.*" \
+	"gdb.MemoryError.*: Cannot access memory at address 0x0.*" \
 	"$test, second test"
   }
   set argc_value [get_integer_valueof "argc" 0]
@@ -338,7 +338,7 @@  proc test_value_in_inferior {} {
   # non-memory value.
   gdb_py_test_silent_cmd "python str = '\"str\"'" "set up str variable" 1
   gdb_test "python print (gdb.parse_and_eval (str).string (length = 10))" \
-      "gdb.error: Attempt to take address of value not located in memory.\r\nError while executing Python code."
+      "gdb.error.*: Attempt to take address of value not located in memory.\r\nError occurred in Python.*"
 
   gdb_test "python print (gdb.parse_and_eval ('shadowed'))" \
       97 "shadowed local value"
@@ -385,7 +385,7 @@  proc test_objfiles {} {
     gdb_test "python print (gdb.objfiles()\[0\].pretty_printers)" "\\\[\\\]"
 
     gdb_test "python gdb.objfiles()\[0\].pretty_printers = 0" \
-      "pretty_printers attribute must be a list.*Error while executing Python code."
+      "pretty_printers attribute must be a list.*Error occurred in Python.*"
 }
 
 proc test_value_after_death {} {
@@ -463,7 +463,7 @@  proc test_subscript_regression {exefile lang} {
 
  # Try to access an int with a subscript.  This should fail.
  gdb_test "python print (intv)" "1" "baseline print of an int Python value"
- gdb_test "python print (intv\[0\])" "gdb.error: Cannot subscript requested type.*" \
+ gdb_test "python print (intv\[0\])" "gdb.error.*: Cannot subscript requested type.*" \
      "Attempt to access an integer with a subscript"
 
  # Try to access a string with a subscript.  This should pass.
@@ -478,7 +478,7 @@  proc test_subscript_regression {exefile lang} {
 
  # Try to access a single dimension array with a subscript to the
  # result.  This should fail.
- gdb_test "python print (pointer\[intv\]\[0\])" "gdb.error: Cannot subscript requested type.*" \
+ gdb_test "python print (pointer\[intv\]\[0\])" "gdb.error.*: Cannot subscript requested type.*" \
      "Attempt to access a single dimension array with a two subscripts"
 
  # Lastly, test subscript access to an array with multiple
@@ -568,7 +568,7 @@  proc test_value_from_buffer {} {
   gdb_test_no_output \
       { python compare_value_bytes_to_mem(v, (int(addr) + (2 * size_a0)), size_a0) }
   gdb_test "python v=gdb.Value(b\[2*size_a0+1:\],tp); print(v)" \
-           "ValueError: Size of type is larger than that of buffer object\..*" \
+           "ValueError.*: Size of type is larger than that of buffer object\..*" \
 	   "attempt to convert smaller buffer than size of type"
   gdb_py_test_silent_cmd "python atp=tp.array(2) ; print(atp)" \
                          "make array type" 0
@@ -580,17 +580,17 @@  proc test_value_from_buffer {} {
   gdb_test "python print(va\[0\])" "1" "print first array element"
   gdb_test "python print(va\[1\])" "2" "print second array element"
   gdb_test "python print(va\[2\])" "3" "print third array element"
-  gdb_test "python print(va\[3\])" "gdb\.error: no such vector element.*" \
+  gdb_test "python print(va\[3\])" "gdb\.error.*: no such vector element.*" \
            "print out of bounds array element"
   gdb_py_test_silent_cmd "python atpbig=tp.array(3)" "make bigger array type" 0
   gdb_test "python vabig=gdb.Value(b,atpbig)" \
-           "ValueError: Size of type is larger than that of buffer object\..*" \
+           "ValueError.*: Size of type is larger than that of buffer object\..*" \
 	   "attempt to construct large value with small buffer" 
   gdb_test "python v=gdb.Value(2048,tp)" \
-           "TypeError: Object must support the python buffer protocol\..*" \
+           "TypeError.*: Object must support the python buffer protocol\..*" \
            "attempt to construct value from buffer with non-buffer object"
   gdb_test "python v=gdb.Value(b,'int'); print(v)" \
-           "TypeError: type argument must be a gdb\.Type\..*" \
+           "TypeError.*: type argument must be a gdb\.Type\..*" \
 	   "attempt to construct value with string as type"
 }
 
@@ -616,7 +616,7 @@  proc test_add_to_history {} {
     # Try adding something that can't be converted to a gdb.Value,
     # this should give an error.
     gdb_test "python idx = gdb.add_history(gdb.GdbError(\"an error\"))" \
-	"TypeError: Could not convert Python object: .*"
+	"TypeError.*: Could not convert Python object: .*"
 }
 
 # Check we can create sub-classes of gdb.Value.
@@ -658,8 +658,8 @@  proc_with_prefix test_value_bytes { } {
   # Test accessing the bytes of an optimised out value.
   gdb_test "python print(gdb.Value(gdb.Value(5).type.optimized_out()).bytes)" \
       [multi_line \
-	   "gdb\\.error: value has been optimized out" \
-	   "Error while executing Python code\\."]
+	   "gdb\\.error.*: value has been optimized out" \
+	   "Error occurred in Python.*"]
 
   # A Python helper function.  Fetch VAR_NAME from the inferior as a
   # gdb.Value.  Read the bytes of the value based on its address, and
@@ -724,11 +724,11 @@  proc_with_prefix test_value_bytes { } {
   gdb_test_no_output "python bytes_as_int.append(0)"
   gdb_test_no_output "python too_many_bytes = bytes(bytes_as_int)"
   gdb_test "python i_value.bytes = too_many_bytes" \
-      "ValueError: Size of type is not equal to that of buffer object\\..*"
+      "ValueError.*: Size of type is not equal to that of buffer object\\..*"
   gdb_test_no_output "python bytes_as_int = bytes_as_int\[0:-2\]"
   gdb_test_no_output "python too_few_bytes = bytes(bytes_as_int)"
   gdb_test "python i_value.bytes = too_few_bytes" \
-      "ValueError: Size of type is not equal to that of buffer object\\..*"
+      "ValueError.*: Size of type is not equal to that of buffer object\\..*"
 
   # Check we get an exception writing to a not_lval.
   gdb_test_no_output "python i_value = gdb.Value(9)" \
diff --git a/gdb/testsuite/gdb.python/python.exp b/gdb/testsuite/gdb.python/python.exp
index c0d398c29b3..175a6de7ca0 100644
--- a/gdb/testsuite/gdb.python/python.exp
+++ b/gdb/testsuite/gdb.python/python.exp
@@ -132,7 +132,7 @@  gdb_test_multiline "post event insertion" \
   "end" ""
 
 gdb_test "python print (someVal)" "1" "test post event execution"
-gdb_test "python gdb.post_event(str(1))" "RuntimeError: Posted event is not callable.*" \
+gdb_test "python gdb.post_event(str(1))" "RuntimeError.*: Posted event is not callable.*" \
     "test non callable class"
 
 send_gdb "python gdb.post_event(lambda: invalid())\n"
@@ -162,7 +162,7 @@  gdb_test_multiple "python print (\"\\n\" * $lines)" $test {
 	pass $test
     }
 }
-gdb_test "q" "Quit.*Error while executing Python.*" "verify pagination beforehand: q"
+gdb_test "q" "Quit.*" "verify pagination beforehand: q"
 
 gdb_test "python if gdb.execute('python print (\"\\\\n\" * $lines)', to_string=True) == \"\\n\" * [expr $lines + 1]: print (\"yes\")" "yes" "gdb.execute does not page"
 
@@ -178,7 +178,7 @@  gdb_test_multiple "python print (\"\\n\" * $lines)" $test {
 	pass $test
     }
 }
-gdb_test "q" "Quit.*Error while executing Python.*" "verify pagination afterwards: q"
+gdb_test "q" "Quit.*" "verify pagination afterwards: q"
 
 gdb_test_no_output "set height 0"
 
@@ -223,7 +223,7 @@  runto $lineno
 
 # Test gdb.decode_line.
 gdb_test "python gdb.decode_line(\"main.c:43\")" \
-    "gdb.error: No source file named main.c.*" "test decode_line no source named main"
+    "gdb.error.*: No source file named main.c.*" "test decode_line no source named main"
 
 with_test_prefix "test decode_line current location" {
     gdb_py_test_silent_cmd "python symtab = gdb.decode_line()" "decode current line" 1
@@ -253,7 +253,7 @@  with_test_prefix "test decode_line" {
     gdb_test "python print (symtab\[1\]\[0\].line)" "26" "python.c:26 line number"
 
     gdb_test "python gdb.decode_line(\"randomfunc\")" \
-	"gdb.error: Function \"randomfunc\" not defined.*" "randomfunc"
+	"gdb.error.*: Function \"randomfunc\" not defined.*" "randomfunc"
     gdb_py_test_silent_cmd "python symtab = gdb.decode_line(\"func1\")" "func1()" 1
     gdb_test "python print (len(symtab))" "2" "func1 length 2"
     gdb_test "python print (len(symtab\[1\]))" "1" "func1 length 1"
diff --git a/gdb/testsuite/gdb.python/tui-window-names.exp b/gdb/testsuite/gdb.python/tui-window-names.exp
index 03cd86bae7e..8236fc9a1a3 100644
--- a/gdb/testsuite/gdb.python/tui-window-names.exp
+++ b/gdb/testsuite/gdb.python/tui-window-names.exp
@@ -39,21 +39,21 @@  foreach c {$ * \{ \} ( ) @ #} {
     set re [string_to_regexp "$c"]
     gdb_test "python gdb.register_window_type('te${c}st', failwin)" \
 	[multi_line \
-	     "gdb.error: invalid character '${re}' in window name" \
-	     "Error while executing Python code\\." ]
+	     "gdb.error.*: invalid character '${re}' in window name" \
+	     "Error occurred in Python.*" ]
 
     gdb_test "python gdb.register_window_type('${c}test', failwin)" \
 	[multi_line \
-	     "gdb.error: invalid character '${re}' in window name" \
-	     "Error while executing Python code\\." ]
+	     "gdb.error.*: invalid character '${re}' in window name" \
+	     "Error occurred in Python.*" ]
 }
 
 # Check that whitespace within a window name is rejected.
 foreach c [list " " "\\t" "\\n" "\\r"] {
     gdb_test "python gdb.register_window_type('te${c}st', failwin)" \
 	[multi_line \
-	     "gdb.error: invalid whitespace character in window name" \
-	     "Error while executing Python code\\." ]
+	     "gdb.error.*: invalid whitespace character in window name" \
+	     "Error occurred in Python.*" ]
 }
 
 # Check some of the characters which are allowed within a window name,
@@ -62,8 +62,8 @@  foreach c {1 _ - .} {
     set re [string_to_regexp "$c"]
     gdb_test "python gdb.register_window_type('${c}test', failwin)" \
 	[multi_line \
-	     "gdb.error: window name must start with a letter, not '${re}'" \
-	     "Error while executing Python code\\." ]
+	     "gdb.error.*: window name must start with a letter, not '${re}'" \
+	     "Error occurred in Python.*" ]
 }
 
 # Check different capitalisations.
diff --git a/gdb/testsuite/gdb.python/tui-window.exp b/gdb/testsuite/gdb.python/tui-window.exp
index ad91fff79cc..e7ff1621fe8 100644
--- a/gdb/testsuite/gdb.python/tui-window.exp
+++ b/gdb/testsuite/gdb.python/tui-window.exp
@@ -50,7 +50,7 @@  Term::check_contents "Window display" "Test: 0"
 
 Term::command "python delete_window_title ()"
 Term::check_contents "error message after trying to delete title" \
-    "TypeError: Cannot delete \"title\" attribute\\."
+    "TypeError.*: Cannot delete \"title\" attribute\\."
 Term::check_contents "title is unchanged" \
     "This Is The Title"
 
diff --git a/gdb/testsuite/lib/gdb-python.exp b/gdb/testsuite/lib/gdb-python.exp
index 6ad20c2b7f1..e27d5c17769 100644
--- a/gdb/testsuite/lib/gdb-python.exp
+++ b/gdb/testsuite/lib/gdb-python.exp
@@ -58,7 +58,7 @@  proc get_python_valueof { exp default {test ""} } {
 proc gdb_py_module_available { name } {
     set available "unknown"
     gdb_test_multiple "python import ${name}" "" {
-	-re -wrap "ModuleNotFoundError: No module named '${name}'.*" {
+	-re -wrap "ModuleNotFoundError.*: No module named '${name}'.*" {
 	    set available false
 	}
 	-re -wrap "ImportError: No module named '?${name}'?.*" {