0

python version: 3.8.1

platform = Windows 10 pro

dev environment : visual studio code, jupyter notebook, command line

I have function that I import from a personal module to find all the current Pandas - DataFrames in memory or the globals(). However I only get the globals() from the module. (I know now that globals() only applies to the module it is called in) <--- This is my problem!

As stated above, I know this is not even remotely able to be done with the normal methodology. Here is my code from start to finish. **Note that I am calling my function from the module and this will only return "module globals()" not 'local globals()' from my current python instance's globals().

Code from "my_module" module:

# my_module.py #

import pandas as pd

module_dataframe = pd.Dataframe({'yourName'},columns = ['Name']) # creates dataframe in my module

def curDFs():
   i ='' # create variable before trying to loop through globals() prevents errors when initiating the loop
   dfList = []
   for i in globals():
       if str(type(globals()[i])) == "<class 'pandas.core.frame.DataFrame'>":
           dfList.append(i)
   return df_list   

so you can see I am creating a Dataframe in my module and creating the function curDFs() to return the name of variables in globals() that are dataframes.

Below is the code from a brand new python session:

# new_window.py #

import my_module as mm
#not importing pandas since already imported into "my_module"

new_dataframe = mm.pd.DataFrame({'name'},columns = ['YourName'])

#calling globals() here will return the "local global variable"->"new_dataframe" created above

#if i call my "curDFs()" function from the module, I return not 'new_dataframe' but the 'module_dataframe' from the module

mm.curDFs()
#returns
['module_dataframe']

I need this to return only the "new_dataframe" variable. How would I do this? I am so stuck, every other post just goes over global and local scope or how to create a config.py file of global variables. However this is going to have to be dynamic and not static as I am seeing the congig.py file to be.

I think it would be a hassle to have to build this function every single instance I spin up. I want to be able import it so I can share with others or minimize the repetitive typing caused by having to copy paste or retype in every new python instance.

Any comments or help here is much appreciated.

1 Answers1

0

Sorry, it seems I did not your question carefully enough.

For your problem I found a hint at the this question.

It seems that the inspect module can do what you want:

# my_module.py #

import pandas as pd
import inspect

module_dataframe = pd.Dataframe({'yourName'},columns = ['Name']) # creates dataframe in my module

def curDFs():
    caller_frame = inspect.stack()[1]
    caller_module = inspect.getmodule(caller_frame[0])
    return [name for name, entry in caller_module.__dict__.items() if str(type(entry)) == "<class 'pandas.core.frame.DataFrame'>"]

This works on my tests, but please note that this may fail under various conditions (some caveats are at the linked post).


This is the expected behaviour. According to the Python Language Reference, Chapter 4.2.2 (Resolution of Names) (emphasis added):

If the global statement occurs within a block, all uses of the name specified in the statement refer to the binding of that name in the top-level namespace. Names are resolved in the top-level namespace by searching the global namespace, i.e. the namespace of the module containing the code block, and the builtins namespace, the namespace of the module builtins. The global namespace is searched first. If the name is not found there, the builtins namespace is searched. The global statement must precede all uses of the name.

The namespace of the module containing the code block in your case is the namespace of my_module.py and only of my_module.py.

Thomas Kläger
  • 17,754
  • 3
  • 23
  • 34
  • Thanks for the detailed explanation, and reference. However this does not tell me anything new as I knew this already (As stated in my question). I am asking if there is a solution that will produce the behavior I am expecting outside of the "Python Resolution of Names" expected behavior. – M.Barkiewicz Apr 09 '20 at 18:40
  • @M.Barkiewicz I've updated my answer so that it hopefully really anwsers your question. – Thomas Kläger Apr 09 '20 at 19:24
  • Thank you, I am going to need to tinker with this to see if I am able to get it working. I think this may be the solution but I am unable to get the scenario to work with your code. I think I am going to be learning the inspect module and attempting to rebuild the solution from there. This at least points me in a new direction. – M.Barkiewicz Apr 09 '20 at 19:52