How can I figure out in my module if the main program uses a specific variable?
I know this does not sound Pythonic, but bear with me for a second.
I am writing a module that depends on some external closed-source module. That module needs to get instantiated to be used (using module.create()).
My module attempts to figure out if my user already loaded that module (easy to do), but then needs to figure out if the module was instantiated. I understand that checking out the type() of each variable can tell me this, but I am not sure how I can get the names of variables defined by the main program. The reason for this is that when one instantiates the model, they also set a bunch of parameters that I do not want to overwrite for any reason.
My attempts so far involved using sys._getframe().f_globals and iterating through the elements, but in my开发者_如何学运维 testing it doesn't work. If I instantiate the module as modInst and then call the function in my module, it fails to show the modInst variable. Is there another solution to this? Sample code provided below.
import sys
if moduleName not in sys.modules:
import moduleName
modInst = moduleName.create()
else:
globalVars = sys._getframe().f_globals
for key, value in globalVars:
if value == "Module Name Instance":
return key
return moduleName.create()
EDIT: Sample code included.
Looks like your code assumes that the .create()
function was called, if at all, by the immediate/direct caller of your function (which you show only partially, making it pretty hard to be sure about what's going on) and the results placed in a global variable (of the module where the caller of your function resides). It all seems pretty fragile. Doesn't that third-party module have some global variables of its own that are affected by whether the module's create
has been called or not? I imagine it would -- where else is it keeping the state-changes resulting from executing the create
-- and I would explore that.
To address a specific issue you raise,
I am not sure how I can get the names of variables defined by the main program
that's easy -- the main program is found, as a module, in sys.modules['__main__']
, so just use vars(sys.modules['__main__'])
to get the global dictionary of the main program (the variable names are the keys in that dictionary, along of course with names of functions, classes, etc -- the module, like any other module, has exactly one top-level/global namespace, not one for variables, a separate one for functions, etc).
Suppose the external closed-sourced module is called extmod
.
Create my_extmod.py
:
import extmod
INSTANTIATED=False
def create(*args,**kw):
global INSTANTIATED
INSTANTIATED=True
return extmod.create(*args,**kw)
Then require your users to import my_extmod
instead of extmod
directly.
To test if the create
function has been called, just check the value of extmod.INSTANTIATED
.
Edit: If you open up an IPython session and type import extmod
, then type
extmod.[TAB]
, then you'll see all the top-level variables in the extmod
namespace. This might help you find some parameter that changes when extmod.create
is called.
Barring that, and barring the possibility of training users to import my_extmod
, then perhaps you could use something like the function below. find_extmod_instance
searches through all modules in sys.modules
.
def find_instance(cls):
for modname in sys.modules:
module=sys.modules[modname]
for value in vars(module).values():
if isinstance(value,cls):
return value
x=find_instance(extmod.ExtmodClass) or extmod.create()
精彩评论