我知道这听起来并不像Pythonic,但是请耐心等一下。
我正在编写一个依赖于某些外部闭源模块的模块。该模块需要实例化才能使用(使用module.create())。
我的模块试图弄清楚我的用户是否已经加载了该模块(易于操作),但随后需要确定模块是否已实例化。我知道检查每个变量的type()可以告诉我这个,但我不知道如何获得主程序定义的变量名称。原因是当一个实例化模型时,它们还设置了一堆我不想因任何原因而覆盖的参数。
到目前为止,我的尝试涉及使用sys._getframe()。f_globals并迭代元素,但在我的测试中它不起作用。如果我将模块实例化为modInst然后在我的模块中调用该函数,则无法显示modInst变量。还有另一个解决方案吗?示例代码如下。
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()
编辑:包含示例代码。
答案 0 :(得分:1)
看起来你的代码假设你的函数的直接/直接调用者调用了.create()
函数(如果有的话)(你只是部分地显示它,很难确定发生了什么) )和结果放在全局变量中(函数调用者所在的模块)。这一切看起来都很脆弱。这个第三方模块是否有一些自己的全局变量受模块的create
是否被调用的影响?我想它会 - 在其他地方保持执行create
导致的状态变化 - 我会探索它。
要解决您提出的具体问题,
我不确定如何获得这些名字 主要定义的变量 程序
这很简单 - 作为一个模块,在sys.modules['__main__']
中找到主程序,所以只需使用vars(sys.modules['__main__'])
来获取主程序的全局字典(变量名是其中的键)字典,当然还有函数,类等的名称 - 模块和任何其他模块一样,具有完全一个顶级/全局命名空间,不是一个用于变量,另一个用于函数等等。)
答案 1 :(得分:0)
假设外部闭源模块被称为extmod
。
创建my_extmod.py
:
import extmod
INSTANTIATED=False
def create(*args,**kw):
global INSTANTIATED
INSTANTIATED=True
return extmod.create(*args,**kw)
然后要求您的用户直接导入my_extmod
而不是extmod
。
要测试是否已调用create
函数,只需检查extmod.INSTANTIATED
的值。
编辑:如果您打开IPython会话并输入import extmod
,请键入
extmod.[TAB]
,然后您将看到extmod
命名空间中的所有顶级变量。这可能有助于您找到一些在调用extmod.create
时更改的参数。
除非这样做,并且禁止培训用户导入my_extmod
的可能性,否则您可能会使用类似下面的功能。 find_extmod_instance
搜索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()