我正在尝试导入一个共享库,其中包含许多用于可视化程序的
Python包装器(特定于
VisIt).这个库的实现方式是首先导入库,这使得一些函数可用,然后调用一个函数来启动visualisaion查看器并使其余的API可用于调用.例如,在下面
form visit import *
print dir()
Launch()
print dir()
第一个print语句包含常用的内置函数和一些其他函数
['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之后的打印称为打印
['AddArgument', 'GetDebugLevel', 'Launch', 'SetDebugLevel', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__warningregistry__']
好像从未调用过Launch.
我的第一个问题是如何通过调用Launch来确保填充全局命名空间?
其次,对Version的调用实际上失败了,错误
NameError: global name ‘Version’ is not defined
即使dir()中的print“Version”返回True.如果我解决了我的第一个问题,这个问题是否会得到解决,还是完全是另一回事?
如果您需要有关共享库上方的更多信息,请与我们联系.我不太了解它是如何写的,但我可以试着找出来.
编辑:在@voithos的回答之后,以下是我采用的解决方案.
正如@voithos所说,“访问使用动态导入,将所有内容带到本地范围……假设您永远不会在全局范围之外调用visit.Launch().”他的(初始)答案允许我通过visit.Launch()使函数可用,使用前缀访问在我的主程序的外部(和)中使用.所有这些惯例.
要从访问导入*导入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的回答.
最佳答案 看来,Visit使用动态导入,将所有内容都带到了本地范围.基本上,他们假设你永远不会在全球范围之外调用visit.Launch().启动函数全部用C语言编写,所以我不确定它是如何导入的.
一种解决方法是将名称从本地范围重新分配到另一个范围. (例如,进入您导入的访问模块)以下是一个示例:
import sys
import visit
def main():
visit.Launch()
# Loop through the locals that were just imported
# and assign the names to the visit module
loc = locals()
for key in loc:
setattr(visit, key, loc[key])
return 0
if __name__=="__main__":
ret = main()
print dir(visit)
sys.exit(ret)
如果您想将名称分配给全局范围,则可以将循环修改为:
loc = locals()
glob = globals()
for key in loc:
glob[key] = loc[key]
但请注意:执行此操作将覆盖之前定义的任何冲突符号名称.例如,如果您定义了Version()函数,则Visit模块中的Version()将覆盖您定义的旧版本.因此,除非你真的需要,否则通常不要用名称来混淆全局范围.