Here is a version using inspect, similar to answers above, but instead of getting the whole stack, only traversing the frames we are interested in (by default the previous 2), and handling the cases that things might be None so you don't get AttributeError but rather the default value returned. You can also configure the depth (if depth is 1 it means go back the immediate caller -- equivalent to inspect.stack[1] -- and so on).
import inspect
def caller_module_name(depth: int = 1, default: str | None = '__main__') -> str | None:
frame = inspect.currentframe()
if not frame:
return default
# Go back up the stack to the caller (or caller's caller, etc.)
# (add 1 to depth to account for this function itself)
for _ in range(depth + 1):
if not (frame := frame.f_back):
return default
if module := inspect.getmodule(frame):
return module.__name__
return default
I'm not sure what the best choice of default value would be, either "__main__", __name__ or just None could be appropriate. The internal function in typing module mentioned below uses the hard-coded string "__main__" as the default, so I have done the same, but what makes sense as a default will probably depend on the application and where/how it is supposed to run.
It might be interesting to see how its done internally in the CPython source code, e.g. here in typing module. However, this is using internal APIs and is only guaranteed to work on CPython, and with no backwards-compatible guarantees. So it would be better to write it using public APIs (in inspect module). (Obviously, it still won't work on Python interpreters without stack frame support, as cautioned in the inspect module docs, but by using inspect module and handling Nones, at least you won't get an exception and can still get a sensible value returned).
caller_namecannot be__main__