1

Basically, can I, for example, use a function defined in a module being imported to print a global variable x defined in the script in which I perform an import? Below, I described a similar problem but tailored more to my specific task.

Structure

.
├── main.py
└── pkg
    ├── __init__.py
    └── a.py

main.py

from pkg.a import f
global_var = 10
f()

pkg/a.py

def f():
    print(global_var)

Desired output:

$ python3 main.py
10
m_ocean
  • 327
  • 3
  • 11

1 Answers1

1

You could check what's inside the dict returned by globals(). But you will have to figure out what is of your interest:

a=2
for key in list(globals().keys()):
    if not key.startswith('_'):  # make sure to define your rules properly here
        print(key, globals().get(key, 'my_default_if_vanished'))

My (filtered) output is:

exit <IPython.core.autocall.ExitAutocall object at 0x000002A9CAE3D700>
quit <IPython.core.autocall.ExitAutocall object at 0x000002A9CAE3D700>
sys <module 'sys' (built-in)>
a 2

Note that since globals might change between the exact moment in which you first looked at it and the moment you try to access some information, it is not advised to iterate on its keys directly (I made a 'snapshot' of the keys into a list and then try to fetch the value for that key, else return a meaningful default).

You might want to check this question for more info.

EDIT The above does not really answer the OP's question. Also according to the documentation on globals():

Return a dictionary representing the current global symbol table. This is always the dictionary of the current module (inside a function or method, this is the module where it is defined, not the module from which it is called).

Hence, my proposal would by keeping a global registry which is maintained by any imported packages/modules:

.
├── main.py
├── globals.py  (with some meaningful var? Maybe `my_globs: dict = {}`
└── pkg
    ├── __init__.py  -> updates `my_globs`
    └── a.py  -> updates and uses `my_globs`

Or maybe via targeted and more maintenance intensive coding via decoration:

.
├── main.py
└── pkg
    ├── __init__.py
    └── a.py

main.py:

from pkg.a import f, pass_globals_on, print_obj_lvl_glob_reg
glob_in_project_main = "YES WE CAN"
f = pass_globals_on(f, globs=globals())
print_obj_lvl_glob_reg(f)

pkg.__init__.py

glob_in_funcs_init = __file__

pkg.a.py:

glob_in_funcs = __file__


def f():
    pass


def pass_globals_on(f, *, globs):
    d = {**globals(), **globs}
    setattr(f, 'obj_lvl_glob_reg', d)
    return f


def print_obj_lvl_glob_reg(f):
    try:
        d = getattr(f, 'obj_lvl_glob_reg')
        for key in list(d.keys()):
            if not key.startswith('_'):  # make sure to define your rules properly here
                print(key, d.get(key, 'my_default_if_vanished'))
    except AttributeError:
        pass

Output (filtered):

glob_in_funcs <path_to_proj>\pkg\a.py
f <function f at 0x0000025CB30A0670>
pass_globals_on <function pass_globals_on at 0x0000025CB30A0820>
print_obj_lvl_glob_reg <function print_obj_lvl_glob_reg at 0x0000025CB30A08B0>
glob_in_project_main YES WE CAN
deponovo
  • 1,114
  • 7
  • 23
  • Thanks but you're calling `globals()` from the same module where you defined `a`! While what I'm asking is how to make the variable available to some imported module – m_ocean Nov 30 '21 at 13:42
  • Should work in the same way. Try the `for` loop in your own `f()` function. – deponovo Nov 30 '21 at 13:48
  • Hm... Really can't make this work. Tried importing the module and calling `globals()` at different moments – nothing. I was saving the output to a file all the time and could't find anything related to the variable. Maybe, you can share you code? – m_ocean Nov 30 '21 at 14:05
  • 1
    You are right. I updated my answer. – deponovo Nov 30 '21 at 15:01
  • Thank you! For now, I ended up using an environment variable instead of defining a variable in a Python module. But I'm definitely going to study your answer – m_ocean Dec 03 '21 at 14:26
  • Setting env vars is a really good idea if you just need text. If you consider the options above, just be careful with the references you may keep unnecessarily that would otherwise be collected by the garbage collector. – deponovo Dec 03 '21 at 15:16