Which way to refer to a Parent Object

As a bit of a noobie to Python forgive me if I am missing something obvious but…

I need to refer to a parent object and I believe there are two ways; either use
sys._getframe(2) or by it’s name '<parentName>.<methodName'. Is there any difference between these two and which is preferable? I have wondered if the sys._getframe(2) would be better for if this code gets run multithreaded, in that case might the '<parentName>.<methodName' way not work correctly.

The use case is where I am running a script.py using exec(); bearing in mind that a script executed by exec() cannot return a value so another method has to be found. This is actually in a class object which is instantiated within the script which needs to pass a variable back to the parent which called exec(). There is actually another difference which depends on where the script is being run from a saved .pyc file, in which case it is sys._getframe(2), or a new file being compiled by importlib.machinery/util, when it issys._getframe(4).

Before anyone questions why; yes there is good reason to do this by executing script files.

It would help to find an appropriate solution for you if you could share what that reason is. You’re clearly working within some unusual requirements here so it might not be obvious how best to handle things without knowing your requirements.

try:
    exec('raise StopIteration(43)')
except StopIteration as e:
    print(e.value)

What exactly do you mean by parent object? It seems like you mean you want to access an object in the exec’ing program from the exec’ed program?

Exec’ing another program is an unusual way to combine programs in the first place. Can you not import the other code, and invoke a function? That way you could explicitly pass the object you needed. Why is exec the best way to do what you need?

Before anyone questions why; yes there is good reason to do this by executing script files.

There are also good reasons not to do it this way, such as the complexity you are asking about here. If you tell us more about your situation, we can help you find the best path.

Ok so technically it can return a value but that is just returning a simple integer, how about returning a couple of strings?

Yes by Parent Object I mean the code object that called the exec(), or even something above it in the calling chain.

The exact same way.

try:
    exec('raise StopIteration(["couple", "strings"])')
except StopIteration as e:
    print(e.value)

Or:

try:
    exec('raise Exception("couple", "strings")')
except Exception as e:
    print(e.args)

(And in both cases, a custom exception type would be better.)

I guarantee there is an easier way to build your system. Can you tell us why you want to exec() other files? Why not import them and run a function they define?

Examining the call stack and accessing values in calling frames is extremely unusual. There will be an easier way to do what you need.

@Stefan2 Very interesting way of returning values from a script, wish I had known that before. Would certainly be a cleaner way.

Have some concern about whether triggering an exception on every hit might have a speed overhead so will have to test that method against the parent object way of doing things.

Each <script>.py is a webpage which combines HTML and Python, don’t want to import any until they are requested hence the exec() method of calling them.

I will echo others’ recommendations that it will be much cleaner to define a function and then call it, but if you MUST do it with exec, what you could do would be to prepopulate its globals with whatever context is needed. Those globals would become available using well-defined names, and your web page can access them to do whatever is needed.

There’s probably no reason to avoid importing them. They won’t take much time or much memory.

You’ve said you were new to Python. There are established ways to build web applications that will avoid the problems you are having.

This is just making me more curious about what you’re trying to do here. Is the HTML stored in Python strings? Are you executing code in the global namespace that has side effects?

I’m sure whatever that overhead is, it’s far less overhead than you’re incurring by using exec() in the first place :stuck_out_tongue:

you can use conditional imports.

def f():
  import math
  return math.pi

This will make sure the module is imported only when needed. There is also an optimization there so that if the function is called often the import short-circuits[1].


  1. not the technically correct term ↩︎

What’s the difference? What does importing do that exec() doesn’t and that you don’t want?

Not executing anything in global namespace but yes html is stored in Python.

I seem to recall from when I first started this that import doesn’t work well; it only runs on the first hit; recurrent requests call it again but import doesn’t actually run again.

Import runs and then the script remains in memory. Exec() just runs a script and then forgets all about it. Anyway import still doesn’t allow returning values.

It’s fine for the script to remain in memory. Scripts are small, and you have lots of memory. Import only runs once, yes. That’s why you put the code in a function, then you can call the function as many times as you need.