You didn't specify what namespace to set the name in, so the name was set in the scope of the fonctions.modifier_dico()
function, not classer_tweet()
. From the exec()
function documentation:
In all cases, if the optional parts are omitted, the code is executed in the current scope.
You'd have to pass in a different dictionary for the name to be set in as a second argument:
exec('dico = {}', namespace)
You can't use exec()
to set locals in a function, unless the name was already assigned to in a given function. This is a hard limitation due optimisations to how a local namespace in a function is accessed. From the same documentation:
Note: The default locals act as described for function locals()
below: modifications to the default locals dictionary should not be attempted. Pass an explicit locals dictionary if you need to see effects of the code on locals after function exec()
returns.
and from the linked locals()
function documentation:
Note: The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.
As such you can't use exec()
to set additional local variables in your view function. You really should use dictionaries anyway for arbitrary namespaces.
You may still see alterations in the locals()
dictionary, but because the function returns a reflection of the actual locals in one direction, that local is not actually available in the function itself. In other words, the actual locals of a function are copied to a dictionary that locals()
returns, additions to that dictionary are not copied back:
>>> def no_local_foo():
... exec('foo = "bar"')
... print(locals())
... foo
...
>>> no_local_foo()
{'foo': 'bar'}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in no_local_foo
NameError: name 'foo' is not defined