0

I have a python script as a string, as example:

exec("sent = {'test': 1}")
global sent
print(sent)

I executed it using exec function, then I accessed the variable using global python command. This way works without problem without using classes, but when I have the same code in a class, like:

class example:
    def fun1(self):
        exec("sent = {'test': 1}")
        global sent
        print(sent)

v = example()
print(v.fun1())

I get the following error:

NameError: name 'sent' is not defined
4
  • Try: exec("global sent;sent = {}") . But avoid using global variables if you can. Commented Nov 19, 2018 at 19:52
  • I can't add "global" to the string, because it's too long Commented Nov 19, 2018 at 19:56
  • Ghanem: What do you mean it's too long? Strings can be almost any length in Python. Commented Nov 20, 2018 at 0:40
  • It's a dataset, someone build it in a code format .. "dummy way" Commented Nov 20, 2018 at 9:26

2 Answers 2

2

You are not passing the global dictionary to modify. Try:

 exec("sent = {}",globals())
Sign up to request clarification or add additional context in comments.

2 Comments

to make the question clear, I append a value to the "sent" variable
The original question was trying to initialize 'sent' to an empty array. This does that. you may also set 'send' to a given dictionary, as in the modified question by: exec("sent = {'test': 1}",globals()) or modify a dictionary that was previously defined as global: exec(" my_global_dictionary['new_key'] = 'new_value'", global()) but adding the second argument, a reference to the global dictionary is crucial. If you do not add this exec creates a global dictionary = {} which is discarded after the function is called.
1

You really should avoid using global variables. Regardless, here's how to do it:

class example:
    def fun1(self):
#        globals sent  # Not needed in this special case.
        exec("sent = {}", globals())
        print('in fun1, "sent" is now', sent )


v = example()
print(v.fun1())  # Result will be None because fun1() doesn't return anything.
print('after call to fun1(), global "sent" is', sent)

Output:

in fun1, "sent" is now {}
None
after call to fun1(), global "sent" is {}

A global declaration only does something inside a function or class method and even then is only needed when the global variable's value is going to be set to something. However, as a special case, one isn't really needed here in the fun1() method because it explicitly passes globals() (but not a separate locals dict) when it calls exec(). It might be a good idea to put one in anyway to make it more clear what's going on.

Using exec() this way is explained in its documentation which says:

If only globals is provided, it must be a dictionary, which will be used for both the global and the local variables.

(emphasis mine)

Here's a way to avoid referencing a global variable at all in the method:

class example:
    def fun1(self):
        namespace = {}
        exec("sent = {}", namespace)
        sent = namespace['sent']  # Retrieve result.
        print('in fun1, "sent" is now', sent )
        return sent

v = example()
sent = v.fun1()
print('after calling fun1(), "sent" got set to', sent)

Output:

in fun1, "sent" is now {}
after calling fun1(), "sent" got set to {}

2 Comments

it didn't work, it prints "None .. regarding to: "You really should avoid using global variables", what is the alternative in such a case?
Ghanem: I think it works now, sorry about that. Alternatives to using globals depend on exactly what you're doing. The most common way is by passing them to the function/method as arguments (if they have mutable values). The other is by returning them from the function/method. i.e. sent = v1.fun1() (assuming you also put a return sent statement at the end of the method).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.