Question:
It feels like the following Python code should be able to run in all circumstances (if print and range is kept unchanged obviously).
for i in range(5):
print(i)
print([(i,j) for j in range(i)])
When run under exec, I find some situations where this code returns an error. Is this an error on Python's side, or am I missing something?
Minimum working example:
import traceback
code_str = r"""
print('\nExec output:')
for i in range(3):
print(i)
print([(i,j) for j in range(i)])
"""
exec_params = [[None, None],
[None, globals()],
[locals(), None],
[{}, None],
[{}, {}],
[None, {}]]
for param0, param1 in exec_params:
try:
#scrubb all variables that could leak from exec
try: del i
except: pass
exec(code_str, param0, param1)
except Exception as e:
print(traceback.format_exc())
Output:
Python 2.7.12 | Python 3.4.4
|
-------------------------------------------------------------------------------------
Params: None, None
-------------------------------------------------------------------------------------
Exec output: | Exec output:
0 | 0
[] | []
1 | 1
[(1, 0)] | [(1, 0)]
2 | 2
[(2, 0), (2, 1)] | [(2, 0), (2, 1)]
-------------------------------------------------------------------------------------
Params: None, globals()
-------------------------------------------------------------------------------------
Exec output: | Exec output:
0 | 0
[] | []
1 | 1
[(1, 0)] | [(1, 0)]
2 | 2
[(2, 0), (2, 1)] | [(2, 0), (2, 1)]
-------------------------------------------------------------------------------------
Params: locals(), None
-------------------------------------------------------------------------------------
Exec output: | Exec output:
0 | 0
[] | []
1 | 1
[(1, 0)] | [(1, 0)]
2 | 2
[(2, 0), (2, 1)] | [(2, 0), (2, 1)]
-------------------------------------------------------------------------------------
Params: {}, None
-------------------------------------------------------------------------------------
Exec output: | Exec output:
0 | 0
[] | []
1 | 1
[(1, 0)] | [(1, 0)]
2 | 2
[(2, 0), (2, 1)] | [(2, 0), (2, 1)]
-------------------------------------------------------------------------------------
Params: {}, {}
-------------------------------------------------------------------------------------
Exec output: | Exec output:
0 | 0
[] | []
1 | 1
[(1, 0)] | Traceback (most recent call last):
2 | File "<ipython-input-126-fe6125860589>", line 23, in <module>
[(2, 0), (2, 1)] | exec(code_str, param0, param1)
| File "<string>", line 5, in <module>
| File "<string>", line 5, in <listcomp>
| NameError: name 'i' is not defined
-------------------------------------------------------------------------------------
Params: None, {}
-------------------------------------------------------------------------------------
Exec output: | Exec output:
0 | 0
[] | []
1 | 1
[(1, 0)] | Traceback (most recent call last):
2 | File "<ipython-input-126-fe6125860589>", line 23, in <module>
[(2, 0), (2, 1)] | exec(code_str, param0, param1)
| File "<string>", line 5, in <module>
| File "<string>", line 5, in <listcomp>
| NameError: name 'i' is not defined