Warning

Most of the documentation was written prior to version 0.5 and needs to be updated. This work has now started for version 0.7 and we aim to have it completed before version 0.8 is available.

Friendlier exec

When using exec(code) with the standard Python interpreter, the code is not retrieved when a traceback occurs. This creates problems for many users, including those interested in projects like Friendly which seek to add improvements to the standard Python tracebacks. Alex Hall has compiled a good list of such projects and discussed this issue on Python-ideas; unfortunately, no one (other than me) seemed to be interested in this topic and the discussion died down.

Friendly has a modified version of exec which makes it possible to retrieve the content of the code that was executed. Below is an example, illustrating some differences between the standard exec and the alternative provided by Friendly. This example uses friendly_traceback but could just as well have used friendly.

  • Notice on line 17 how no content is shown from the file <string> when using exec.

  • On line 18, Python (3.10) does offer a suggestion for a fix but ``friendly_traceback cannot do the same as the code is not available.

  • Using friendly_exec on line 23 solves this problem.

 1     > python -m friendly_traceback
 2     Friendly-traceback version 0.7.50
 3     Python version: 3.10.6
 4     Use exit() or Ctrl-Z plus Return to exit.
 5     Type 'Friendly' for help on special functions/methods.
 6
 7     [1]: from math import pi
 8
 9     [2]: code = "a = 2 * Pi"
10
11     [3]: exec(code)
12
13     Traceback (most recent call last):
14       Code block [3], line 1
15         exec(code)
16       File "<string>", line 1, in <module>
17
18     NameError: name 'Pi' is not defined. Did you mean: 'pi'?
19
20     [4]: why()
21     I have no suggestion to offer.
22
23     [5]: friendly_exec(code)
24
25     Traceback (most recent call last):
26       Code block [5], line 1
27         friendly_exec(code)
28       File "FRIENDLY:\source_cache.py", line 127, in friendly_exec
29         return exec(code, globals_, locals_)
30       File "<friendly-exec-0>", line 1, in <module>
31         a = 2 * Pi
32     NameError: name 'Pi' is not defined. Did you mean: 'pi'?
33
34             Did you mean `pi`?
35
36
37     [6]: why()
38
39         In your program, no object with the name `Pi` exists.
40         The similar name `pi` was found in the local scope.
41
42
43     [7]: where()
44
45         Execution stopped on line `1` of code block [5].
46
47         -->1| friendly_exec(code)
48               ^^^^^^^^^^^^^^^^^^^
49
50                 code:  'a = 2 * Pi'
51                 friendly_exec:  <function friendly_exec>
52
53         Exception raised on line `1` of file '<friendly-exec-0>'.
54
55         -->1| a = 2 * Pi
56                       ^^