【发布时间】:2012-01-11 01:05:05
【问题描述】:
我正在尝试导入一个共享库,其中包含许多用于可视化程序的 Python 包装器(具体来说是VisIt)。这个库的实现方式是,首先导入库,这使得一些函数可用,然后调用一个函数来启动可视化查看器并使其余 API 可供调用。比如下面的
form visit import *
print dir()
Launch()
print dir()
第一个打印语句包含常用的内置函数和一些其他函数
['AddArgument', 'GetDebugLevel', 'Launch', 'SetDebugLevel', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__warningregistry__']
第二次打印输出
['ActivateDatabase', 'AddArgument', 'AddColorTable', 'AddOperator', 'AddPlot', ... ]
等等
我希望改为在函数中调用Launch(这样我就可以处理并将参数传递给Launch)。但是,当我这样做时,在调用 Launch 后可用的函数不在全局命名空间中,而是在函数本地的命名空间中。所以在下面的例子中
import sys
from visit import *
def main():
Launch()
print dir()
if "Version" in dir()
print Version() # This is made available by call to Launch() above
return 0
if __name__=="__main__":
ret = main()
print dir()
sys.exit(ret)
main 中的 print 语句将打印出来
['ActivateDatabase', 'AddArgument', 'AddColorTable', 'AddOperator', 'AddPlot', ... ]
如上,而在main 之后的print 被称为 prints
['AddArgument', 'GetDebugLevel', 'Launch', 'SetDebugLevel', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__warningregistry__']
好像Launch 从未被调用过。
我的第一个问题是如何确保通过调用 Launch 填充全局命名空间?
其次,对Version 的调用实际上失败了,并出现错误
NameError:未定义全局名称“版本”
即使print "Version" in dir() 返回True。如果我解决了我的第一个问题,这个问题是否会得到解决,或者这完全是另外一回事?
如果您需要共享库上方的更多信息,请告诉我。我不太了解它是如何编写的,但我可以尝试找出答案。
编辑:按照@voithos 的回答,以下是我采用的解决方案。
正如@voithos 所说,“访问使用动态导入将所有内容都带到本地范围......假设您永远不会在全局范围之外调用visit.Launch()。”他的(初始)回答允许我使用前缀 visit. 与所有这些例程一起使用 visit.Launch() 提供的功能,以便在我的主例程之外(和之内)使用。
要将 VisIt 例程导入为from visit import *,以便可以在没有visit. 前缀的情况下调用它们,我将@voithos 在main 中对setattr 的使用修改为以下
# Loop through the local namespace and add the names that were just
# imported to the module namespace
loc = locals()
for key in loc:
setattr(sys.modules[__name__], key, loc[key])
那么 VisIt 例程在模块级别可用,一切看起来都很好。
感谢@voithos 的回答。
【问题讨论】:
-
我最初将我的编辑作为答案发布,但觉得最好将其作为我的问题的更新。