3

I want to access the calling environment from an imported module.

import child
…
def test(xxx):
   print("This is test " + str(xxx))

child.main()
…

now on child:

import   inspect
def main():
     caller = inspect.currentframe().f_back
     caller.f_globals['test']("This is my test")

This works, but it's not fancy. Is there a simplification like 'self' when use in a class? the idea is to do: caller.test('abc') instead.

One option to pass the caller as a parameter like: child.main(self), however self is not available in this context.

Python only load one version of a module so, tempted with this idea:

import sys
myself=sys.modules[__name__]

a then sending myself to the child:

…
child.main(myself)
…

Creates a reference to (a new) module, but not the running one, this is like creating a new class: one code buy a different environment.

fcm
  • 1,247
  • 15
  • 28
  • Do you need to access the function as an attribute/key? Cause I think the simpler option is to take it as an argument to `child.main`, i.e. `def main(x): x("This is my test")`, then `child.main(test)` – wjandrea Jun 27 '19 at 17:04
  • possibly related: [How can I access the current executing module or class name in Python?](https://stackoverflow.com/q/602846/4518341) – wjandrea Jun 27 '19 at 17:11
  • @wjandrea I have a few hundred function/variables that need to access. – fcm Jun 27 '19 at 17:18
  • 1
    I see. So maybe you could pass the current module object instead of every individual object. See https://stackoverflow.com/q/2933470/4518341 – wjandrea Jun 27 '19 at 17:27
  • So you specifically need to access the current module and not a copy of it? Why do you need that? This seems like an [XY problem](https://meta.stackexchange.com/q/66377/343832), or at least like you've left off some requirements/details. – wjandrea Jun 28 '19 at 13:54
  • 1
    This is part of a `nginx` web project using `uwsgi`. The calling process, provide many uwsgi global functions and data, I need to access them from the child. Using sys.modules[\_\_name\_\_] gives me access to shared code, but a new set of unshared global variables. However, inspect.currentframe() gives the global variables as expected. – fcm Jun 28 '19 at 15:28

1 Answers1

0

If you already have a way of accessing the correct functions and data that works, why not just store f_globals on an instance of a wrapper class and then call things from the instance as if they were unbound properties? You could use the class itself, but using an instance ensures that the data you get from the imported file are valid when you create the object. Then you can access using the dot operator the way you want. This is your child file:

import inspect

class ImportFile:
  def __init__(self, members):
    self.__dict__.update(members)

def main():
  caller = inspect.currentframe().f_back
  imported_file = ImportFile(caller.f_globals)
  imported_file.test("This is my test")

Outputs:

This is test This is my test

Admittedly, I don't have your setup, importantly the module you're trying to pull from, so it's hard to confirm whether or not this will work for you even though it has for me, but I think you could also use your method of calling main with globals() or even inspect.getmembers() since while inside the module you're importing you're still on the frame you're accessing with f_back from inside child.

The imported module:

import child

def test(xxx):
  print("This is test " + str(xxx))

child.main(globals())

Child:

import inspect

class ImportFile:
  def __init__(self, members):
    self.__dict__.update(members)

def main(caller):
  imported_file = ImportFile(caller)
  imported_file.test("This is my test")

Outputs:

This is test This is my test