Getting globals of the caller, not the defining module

S

Steven D'Aprano

Suppose I have a function that needs access to globals:

# module A.py
def spam():
g = globals() # this gets globals from A
introspect(g)

As written, spam() only sees its own globals, i.e. those of the module in
which spam is defined. But I want spam to see the globals of the caller.

# module B
import A
A.spam() # I want spam to see globals from B


I can have the caller explicitly pass the globals itself:

def spam(globs=None):
if globs is None:
globs = globals()
introspect(globs)


But since spam is supposed to introspect as much information as possible,
I don't really want to do that. What (if anything) are my other options?
 
C

Chris Angelico

But since spam is supposed to introspect as much information as possible,
I don't really want to do that. What (if anything) are my other options?

You're playing with introspection, so I'd look at poking around in the
stack trace. It'll be esoteric, but I think this is the right place to
use it.

ChrisA
 
S

sg552

(Sorry for posting through GG, I'm at work.)

Suppose I have a function that needs access to globals:

# module A.py
def spam():
g = globals() # this gets globals from A
introspect(g)

As written, spam() only sees its own globals, i.e. those of the module in
which spam is defined. But I want spam to see the globals of the caller.

# module B
import A
A.spam() # I want spam to see globals from B

I can have the caller explicitly pass the globals itself:

def spam(globs=None):
if globs is None:
globs = globals()
introspect(globs)

But since spam is supposed to introspect as much information as possible,
I don't really want to do that. What (if anything) are my other options?

How about this?

# module A.py
import inspect
def spam():
return inspect.stack()[1][0].f_globals

# module B.py
import A
print(A.spam() is globals()) # prints True
def f():
return A.spam()

# module C.py
import B
print(B.f() is vars(B)) # prints True

I don't really know what I'm doing but I guess it won't work in alternative implementations of Python.
 
T

Terry Reedy

(Sorry for posting through GG, I'm at work.)

Suppose I have a function that needs access to globals:

# module A.py
def spam():
g = globals() # this gets globals from A
introspect(g)

As written, spam() only sees its own globals, i.e. those of the module in
which spam is defined. But I want spam to see the globals of the caller.

# module B
import A
A.spam() # I want spam to see globals from B

I can have the caller explicitly pass the globals itself:

def spam(globs=None):
if globs is None:
globs = globals()
introspect(globs)

But since spam is supposed to introspect as much information as possible,
I don't really want to do that. What (if anything) are my other options?

How about this?

# module A.py
import inspect
def spam():
return inspect.stack()[1][0].f_globals

In Python 3, the attribute is __globals__. In either case, it is only
defined on Python coded functions, so one should be prepared for it to
not exist. That possibility is real because there *are* builtins like
map and filter that take function args and call them.

Inspect has been modified in Py 3, but stack is still there.
 
R

Rotwang

(Sorry for posting through GG, I'm at work.)

Suppose I have a function that needs access to globals:

# module A.py
def spam():
g = globals() # this gets globals from A
introspect(g)

As written, spam() only sees its own globals, i.e. those of the
module in
which spam is defined. But I want spam to see the globals of the caller.

# module B
import A
A.spam() # I want spam to see globals from B

I can have the caller explicitly pass the globals itself:

def spam(globs=None):
if globs is None:
globs = globals()
introspect(globs)

But since spam is supposed to introspect as much information as
possible,
I don't really want to do that. What (if anything) are my other options?

How about this?

# module A.py
import inspect
def spam():
return inspect.stack()[1][0].f_globals

In Python 3, the attribute is __globals__.

Er... no it isn't? Sorry if I'm mistaken but I believe you're thinking
of the attribute formerly known as func_globals. But in the above
inspect.stack()[1][0] is not a function, it's a frame object. In fact
it's the same thing as sys._getframe().f_back, I think.
 
R

Rotwang

(Sorry for posting through GG, I'm at work.)

Suppose I have a function that needs access to globals:

# module A.py
def spam():
g = globals() # this gets globals from A
introspect(g)

As written, spam() only sees its own globals, i.e. those of the module in
which spam is defined. But I want spam to see the globals of the caller.

# module B
import A
A.spam() # I want spam to see globals from B

I can have the caller explicitly pass the globals itself:

def spam(globs=None):
if globs is None:
globs = globals()
introspect(globs)

But since spam is supposed to introspect as much information as possible,
I don't really want to do that. What (if anything) are my other options?

How about this?

# module A.py
import inspect
def spam():
return inspect.stack()[1][0].f_globals

Bump. Did this do what you wanted, or not?
 

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,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top