2010-02-25 47 views
1

我知道这听起来不像Pythonic,但忍受了我一秒钟。如何在我的模块中弄清楚主程序是否使用了特定的变量?

我在写一个模块,它依赖于某些外部闭源模块。该模块需要实例化(使用module.create())。

我的模块试图弄清楚我的用户是否已经加载了这个模块(很容易做到),但是之后需要弄清楚模块是否被实例化了。我明白检查每个变量的类型()可以告诉我这一点,但我不知道如何获取主程序定义的变量名称。其原因是,当一个实例化模型时,他们还设置了一堆我不想因任何原因而被覆盖的参数。

我到目前为止的尝试都涉及到使用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() 

编辑:包括示例代码。

回答

1

看起来你的代码假定.create()函数被调用,如果有的话,你的功能的直接/直接调用者(你只显示部分,使得它相当困难是肯定发生了什么)将结果置于全球变量(您的函数的调用者所在的模块的位置)中。这一切似乎都很脆弱。这个第三方模块是否有一些自己的全局变量受到模块的create是否被调用的影响?我想它会 - 在其他地方保持执行create产生的状态变化 - 我会探索它。

为了解决你提出一个具体问题,

我不知道我怎么能得到的名称由主 程序

,很容易定义的变量 - 主程序作为一个模块被发现在sys.modules['__main__'],所以只需使用vars(sys.modules['__main__'])来获取主程序的全局字典(变量名称是该字典中的键,当然还有函数名,类等等 - 模块,像任何其他模块一样,确切地说有一个顶级/全局命名空间,不是一个用于变量,另一个用于函数等)。

+0

Alex, 非常感谢。 sys.modules ['__ main__']比sys._getframe(1).f_globals更优雅。当然,他们都假设主程序是调用create函数的程序,而不是它们自己的模块之一,但我不确定这很容易解决(除非我遍历所有的sys.modules)。 至于.create()函数创建任何变量 - 情况并非如此。所有变量都存储在create()为您创建的对象中,并且没有任何内容存储在外部。这就是为什么我在这方面遇到很多麻烦。 有没有办法找到对象,无论模块? – 2010-02-25 20:10:24

+0

@Michalis,一般来说,不,没有完全一般的方法来找到一个对象,而不知道它的存储位置。但是,您可以尝试http://docs.python.org/library/gc.html?highlight=gc#gc.get_objects - 它会返回所有列表和字典(以及其他一些容器)供您检查。当然,对于大型项目来说,这种检查可能需要相当长一段时间! – 2010-02-25 21:18:18

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() 
+0

unutbu, 这正是我的想法,但我意识到我需要一种方法来确保如果我的用户不遵循指示(我相信这几乎总是如此),我不会擦除他们的工作。这就是为什么我需要知道他们是否自己实例化它。当然,如果这是不可能的,我需要找出另一种方法来确保他们不会太过于愚蠢。 – 2010-02-25 19:33:15

+0

@Michalis:好的,这里有另外一个想法:你提到有很多你不想覆盖的参数。你能找出这些参数的默认值是什么(或者它们是否存在),然后将它们与它们的当前值进行比较?如果不同,那么你知道用户必须调用'create' ...? – unutbu 2010-02-25 19:39:36

+0

是的,我可以。但是所有这些参数都是通过实例化对象来访问的,这正是我试图找到的。因此,我仍然需要查找它是否已经实例化以及它使用什么名称。 – 2010-02-25 19:42:04

相关问题