Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #59065 > unrolled thread

Getting globals of the caller, not the defining module

Started bySteven D'Aprano <steve+comp.lang.python@pearwood.info>
First post2013-11-11 11:25 +0000
Last post2013-11-15 08:23 +0000
Articles 7 — 5 participants

Back to article view | Back to comp.lang.python


Contents

  Getting globals of the caller, not the defining module Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-11-11 11:25 +0000
    Re: Getting globals of the caller, not the defining module Chris Angelico <rosuav@gmail.com> - 2013-11-11 22:34 +1100
    Re: Getting globals of the caller, not the defining module sg552@hotmail.co.uk - 2013-11-11 04:02 -0800
      Re: Getting globals of the caller, not the defining module Terry Reedy <tjreedy@udel.edu> - 2013-11-11 20:57 -0500
        Re: Getting globals of the caller, not the defining module Rotwang <sg552@hotmail.co.uk> - 2013-11-12 08:29 +0000
      Re: Getting globals of the caller, not the defining module Rotwang <sg552@hotmail.co.uk> - 2013-11-14 20:56 +0000
        Re: Getting globals of the caller, not the defining module Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-11-15 08:23 +0000

#59065 — Getting globals of the caller, not the defining module

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-11-11 11:25 +0000
SubjectGetting globals of the caller, not the defining module
Message-ID<5280beb6$0$29976$c3e8da3$5496439d@news.astraweb.com>
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?


-- 
Steven

[toc] | [next] | [standalone]


#59066

FromChris Angelico <rosuav@gmail.com>
Date2013-11-11 22:34 +1100
Message-ID<mailman.2369.1384169700.18130.python-list@python.org>
In reply to#59065
On Mon, Nov 11, 2013 at 10:25 PM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> 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

[toc] | [prev] | [next] | [standalone]


#59071

Fromsg552@hotmail.co.uk
Date2013-11-11 04:02 -0800
Message-ID<aba4de87-cbf6-4c28-8ae3-da2d2a69eeb4@googlegroups.com>
In reply to#59065
(Sorry for posting through GG, I'm at work.)

On Monday, November 11, 2013 11:25:42 AM UTC, Steven D'Aprano wrote:
> 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.

[toc] | [prev] | [next] | [standalone]


#59136

FromTerry Reedy <tjreedy@udel.edu>
Date2013-11-11 20:57 -0500
Message-ID<mailman.2419.1384221452.18130.python-list@python.org>
In reply to#59071
On 11/11/2013 7:02 AM, sg552@hotmail.co.uk wrote:
> (Sorry for posting through GG, I'm at work.)
>
> On Monday, November 11, 2013 11:25:42 AM UTC, Steven D'Aprano wrote:
>> 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.

> # 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.
>


-- 
Terry Jan Reedy

[toc] | [prev] | [next] | [standalone]


#59163

FromRotwang <sg552@hotmail.co.uk>
Date2013-11-12 08:29 +0000
Message-ID<l5sou5$inl$1@dont-email.me>
In reply to#59136
On 12/11/2013 01:57, Terry Reedy wrote:
> On 11/11/2013 7:02 AM, sg552@hotmail.co.uk wrote:
>> (Sorry for posting through GG, I'm at work.)
>>
>> On Monday, November 11, 2013 11:25:42 AM UTC, Steven D'Aprano wrote:
>>> 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.

[toc] | [prev] | [next] | [standalone]


#59477

FromRotwang <sg552@hotmail.co.uk>
Date2013-11-14 20:56 +0000
Message-ID<l63de3$ef6$1@dont-email.me>
In reply to#59071
On 11/11/2013 12:02, sg552@hotmail.co.uk wrote:
> (Sorry for posting through GG, I'm at work.)
>
> On Monday, November 11, 2013 11:25:42 AM UTC, Steven D'Aprano wrote:
>> 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?

[toc] | [prev] | [next] | [standalone]


#59506

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-11-15 08:23 +0000
Message-ID<5285d9fa$0$29975$c3e8da3$5496439d@news.astraweb.com>
In reply to#59477
On Thu, 14 Nov 2013 20:56:34 +0000, Rotwang wrote:

[...]
>> 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?


Sort of. If anything, it convinced me that I don't, in fact, want what I 
thought I wanted.

I'm still playing around with the code, but it's looking likely that auto-
detecting the caller's globals is not really what I want.


-- 
Steven

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web