Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variable not define after exec('variable = value')

I'm quite stuck on this one ^^. I have a view in which I use a function named modifier_dico which is inside a file named fonctions.py. The 2 first lines of modifier_dico are as follows :

def modifier_dico(tweet,nom_dico, dico_cat):
    exec('dico= {}')

My view looks like :

def classer_tweet(request):
    modifier_dico(tweet.text,"dico_status.txt", {})

When I try to access this view, I get name 'dico' is not defined on Django's debug page.

But when I look at the local vars of modifier_dico in the traceback, I have the variable dico with the value {}

It looks like exec() is not working as I expect.

like image 342
Mehdi Avatar asked Feb 11 '16 10:02

Mehdi


People also ask

What is exec () in Python?

The exec() function executes the specified Python code. The exec() function accepts large blocks of code, unlike the eval() function which only accepts a single expression.

How do you check if a variable is defined or not in Python?

Python doesn't have a specific function to test whether a variable is defined, since all variables are expected to have been defined before use, even if initially assigned the None object.

Why is variable not defined Python?

Conclusion # The Python "NameError: name is not defined" occurs when we try to access a variable or function that is not defined or before it is defined. To solve the error, make sure you haven't misspelled the variable's name and access it after it has been declared.

How do you declare an undefined variable in Python?

An undefined variable in the source code of a computer program is a variable that is accessed in the code but has not been declared by that code. In some programming languages, an implicit declaration is provided the first time such a variable is encountered at compile time.


1 Answers

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
like image 176
Martijn Pieters Avatar answered Oct 12 '22 16:10

Martijn Pieters