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 usingexec
.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 ^^