Safe to modify globals(), or not?

R

Robert Dodier

Hello,

I'm interested in introducing new variables into the environment
of a Python interpreter or program.

In reading through old posts to this newsgroup, I see there is
an often-repeating warning against modifying the contents of locals().
Fair enough. However, is there anything wrong with modifying globals()
?

In the list of built-in functions
(http://www.python.org/doc/lib/built-in-funcs.html)
locals() has an explicit warning, globals() doesn't. Does that mean
it's safe to modify globals() ?

By the way, is there another way to introduce a new variable into
a scope (local or global) other than assigning directly to the
dictionary returned by locals() or globals() ?

Just some context -- I want to parse strings written in a
"little language" and then have new variables show up in the Python
environment so the user can manipulate them. E.g.,
Interjection

Any light you can shed on this issue will be appreciated.
Thanks for not getting distracted about whether this is useful.

regards,
Robert Dodier
 
A

Aahz

In reading through old posts to this newsgroup, I see there is
an often-repeating warning against modifying the contents of locals().
Fair enough. However, is there anything wrong with modifying globals()
?

Not wrong, exactly, but there may well be in the future, and there are
better ways currently.
By the way, is there another way to introduce a new variable into
a scope (local or global) other than assigning directly to the
dictionary returned by locals() or globals() ?

For locals, it's a lot trickier, but you're less likely to want to do
that.
Just some context -- I want to parse strings written in a
"little language" and then have new variables show up in the Python
environment so the user can manipulate them. E.g.,

Interjection

import __main__
tmp = parse_funky_language("Hey, this is far out, man.")
setattr(__main__, tmp.name, tmp.value)

In the context of the interactive interpreter, it's a bit harder to do;
I don't remember off-hand what the namespace of the interpreter is.
--
Aahz ([email protected]) <*> http://www.pythoncraft.com/

"The joy of coding Python should be in seeing short, concise, readable
classes that express a lot of action in a small amount of clear code --
not in reams of trivial code that bores the reader to death." --GvR
 
T

Terry Reedy

Robert Dodier said:
Hello,

I'm interested in introducing new variables into the environment
of a Python interpreter or program.

This is a bit vague and not obviously connected to your question. Let's
ignore this.
Globals() returns the module-specific 'global' namespace, as opposed to the
function-local namespace.
In reading through old posts to this newsgroup, I see there is
an often-repeating warning against modifying the contents of locals().

Outside of functions, locals() == globals(). Inside of functions, where
locals() != globals() and is therefore not redundant and potentially
useful, the result is only guaranteed to be a read-only *copy* of the
current state of the local namespace. Even if it is writable, the changes
may only change the *copy* and not the local namespace itself. This makes
for subtle bugs when the programmer expects (if falsely) that changes are
propagated.
Fair enough. However, is there anything wrong with modifying globals()

No. "globals()['a'] = 3" is exactly the same as "a=3" executed at module
scope, outside of functions. The purpose is to allow you to set a variable
whose name you do not know until runtime. An example, as in your
application, is when the name comes from user input.

Having said that, you do need to ask yourself whether you really want to
put user variables in the global namespace that your are using yourself for
your code, which will wreck havoc when there is a name collision. Or
whether you should put them is a separate namespace dict such as uservars.
And then exec user code with uservars as the globals. Or something like
that.

Terry J. Reedy
 
P

Peter Otten

Aahz said:
import __main__
tmp = parse_funky_language("Hey, this is far out, man.")
setattr(__main__, tmp.name, tmp.value)

In the context of the interactive interpreter, it's a bit harder to do;
I don't remember off-hand what the namespace of the interpreter is.

You don't need to :)

Python 2.3.3 (#1, Jan 3 2004, 13:57:08)
[GCC 3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.'__main__'

Peter
 
A

Aahz

Aahz said:
import __main__
tmp = parse_funky_language("Hey, this is far out, man.")
setattr(__main__, tmp.name, tmp.value)

In the context of the interactive interpreter, it's a bit harder to do;
I don't remember off-hand what the namespace of the interpreter is.

You don't need to :)

Python 2.3.3 (#1, Jan 3 2004, 13:57:08)
[GCC 3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.'__main__'

Yes, but how do you access that from a module?
--
Aahz ([email protected]) <*> http://www.pythoncraft.com/

"The joy of coding Python should be in seeing short, concise, readable
classes that express a lot of action in a small amount of clear code --
not in reams of trivial code that bores the reader to death." --GvR
 
P

Peter Otten

Aahz said:
Aahz said:
import __main__
tmp = parse_funky_language("Hey, this is far out, man.")
setattr(__main__, tmp.name, tmp.value)

In the context of the interactive interpreter, it's a bit harder to do;
I don't remember off-hand what the namespace of the interpreter is.

You don't need to :)

Python 2.3.3 (#1, Jan 3 2004, 13:57:08)
[GCC 3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
'__main__'

Yes, but how do you access that from a module?

<interp.py>
import sys
import __main__
setattr(sys.modules["__main__"], "name", "value")
__main__.anotherName = "another value"
</interp.py>

Python 2.3.3 (#1, Jan 3 2004, 13:57:08)
[GCC 3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
Or is this a misunderstanding continued?

Peter
 
J

Josiah Carlson

Fair enough. However, is there anything wrong with modifying globals()


No. "globals()['a'] = 3" is exactly the same as "a=3" executed at module
scope, outside of functions. The purpose is to allow you to set a variable
whose name you do not know until runtime. An example, as in your
application, is when the name comes from user input.

I personally enjoy modifying globals() as it suits my needs. Another
statement that is quite useful is global..... global k
.... k = i
....
Really only useful for when you know the name of the variable before
runtime, but then again, one could always:.... exec('global %s;%s = i'%(name, name))
....10


MMM, global manipulation. Now if only there was a python function for
global dominance, though perhaps globals().clear() is sufficient.
Mua-hah-hah.

- Josiah
 
A

Aahz

Aahz said:
Aahz wrote:

import __main__
tmp = parse_funky_language("Hey, this is far out, man.")
setattr(__main__, tmp.name, tmp.value)

In the context of the interactive interpreter, it's a bit harder to do;
I don't remember off-hand what the namespace of the interpreter is.

You don't need to :)

Python 2.3.3 (#1, Jan 3 2004, 13:57:08)
[GCC 3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
__name__
'__main__'

Yes, but how do you access that from a module?

<interp.py>
import sys
import __main__
setattr(sys.modules["__main__"], "name", "value")
__main__.anotherName = "another value"
</interp.py>

Python 2.3.3 (#1, Jan 3 2004, 13:57:08)
[GCC 3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
Or is this a misunderstanding continued?

<smacks head> No, it's a brain fart; for some reason, I was thinking
that "__main__" == "currently executing module".
--
Aahz ([email protected]) <*> http://www.pythoncraft.com/

"The joy of coding Python should be in seeing short, concise, readable
classes that express a lot of action in a small amount of clear code --
not in reams of trivial code that bores the reader to death." --GvR
 
E

Elaine Jackson

Have you considered " globals()[name] = i " ?

|
| >>Fair enough. However, is there anything wrong with modifying globals()
| >
| >
| > No. "globals()['a'] = 3" is exactly the same as "a=3" executed at module
| > scope, outside of functions. The purpose is to allow you to set a variable
| > whose name you do not know until runtime. An example, as in your
| > application, is when the name comes from user input.
|
| I personally enjoy modifying globals() as it suits my needs. Another
| statement that is quite useful is global.
| >>> def set_global_k(i):
| ... global k
| ... k = i
| ...
| >>> set_global_k(5)
| >>> k
| 5
| >>> set_global_k(6)
| >>> k
| 6
| >>>
|
| Really only useful for when you know the name of the variable before
| runtime, but then again, one could always:
| >>> def set_global_name(i, name):
| ... exec('global %s;%s = i'%(name, name))
| ...
| >>> set_global_name(10, 'l')
| >>> l
| 10
|
|
| MMM, global manipulation. Now if only there was a python function for
| global dominance, though perhaps globals().clear() is sufficient.
| Mua-hah-hah.
|
| - Josiah
 
R

Robert Dodier

Peter Otten said:
<interp.py>
import sys
import __main__
setattr(sys.modules["__main__"], "name", "value")
__main__.anotherName = "another value"
</interp.py>

Thanks a lot, Peter, this is just the right thing.
I guess modifying globals() is a non-issue, as it turns out.
I appreciate your help.

Robert Dodier
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,521
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top