Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 导入共享库和全局命名空间_Python_Shared Libraries - Fatal编程技术网

Python 导入共享库和全局命名空间

Python 导入共享库和全局命名空间,python,shared-libraries,Python,Shared Libraries,我正在尝试导入一个共享库,其中包含许多用于可视化程序的Python包装(具体来说)。此库的实现方式如下:首先导入库,使一些函数可用,然后调用一个函数,该函数启动visualisaion查看器,并使API的其余部分可供调用。例如,在下面的 form visit import * print dir() Launch() print dir() # Loop through the local namespace and add the names that were just # importe

我正在尝试导入一个共享库,其中包含许多用于可视化程序的Python包装(具体来说)。此库的实现方式如下:首先导入库,使一些函数可用,然后调用一个函数,该函数启动visualisaion查看器,并使API的其余部分可供调用。例如,在下面的

form visit import *
print dir()
Launch()
print dir()
# 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])
第一个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
之后的
print
称为prints

['AddArgument', 'GetDebugLevel', 'Launch', 'SetDebugLevel', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__warningregistry__']
好像从未调用过
Launch

我的第一个问题是如何确保全局命名空间由对
Launch
的调用填充

其次,调用
Version
实际上失败了,并出现了错误

NameError:未定义全局名称“版本”

即使在dir()中打印“版本”返回
True
。如果我解决了我的第一个问题,这个问题会得到解决吗?或者这完全是另一回事

如果您需要有关共享库的更多信息,请告诉我。我不知道它是怎么写的,但我可以试试看

编辑:根据@voithos的回答,以下是我采用的解决方案

正如@voithos所说,“Visit使用动态导入,将所有内容都带到本地范围……假设您永远不会在全局范围之外调用
Visit.Launch()
。”他的(初始)回答允许我将
Visit.Launch()
提供的函数用于我的主例程的外部(和内部),在所有这些例程中使用前缀
visit.

要从VisIt import*导入作为
的VisIt例程,以便在不使用
VisIt.
前缀的情况下调用它们。
我将
main
中@voithos'对
setattr
的使用修改为:

form visit import *
print dir()
Launch()
print dir()
# 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])
然后,在模块级别上可以使用访问例程,并且看起来一切正常


感谢@voithos提供您的答案。

我从未使用过VisIt,但根据他们的文档,您需要执行以下操作:

import visit

def main():    
    visit.Launch()
它将所有函数导入“visit”命名空间。然后,您只需通过访问名称空间与库的函数进行接口。例如:

visit.Version()

似乎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()
函数,则访问模块中的
Version()
将覆盖您定义的旧函数。因此,除非您真的需要,否则通常最好不要将全局范围中的名称弄乱。

这给了我同样的问题:如果我使用
import-visit
并在调用
main
后用
print-dir(visit)
替换print语句,那么我就得不到完整的API,只调用
启动
之前最初可用的函数。我应该说,我之所以使用
从访问导入*
而不是
导入访问
,是有原因的。我的问题是,
visit.Launch
提供的功能在
main
之外是无法访问的。感谢您的回答@voithos-这很好地工作并访问。例如,现在可以在
main
内和调用
main
后成功调用版本。但是,我可以使用类似的解决方法将
main
的本地名称添加到全局名称空间中。如果我想在标准Python解释器中使用与VisIt相同的脚本,这一点很重要。@Chris:当然,这很简单。只需分配给全局模块,而不是
访问
。您可以使用
globals()
访问全局符号表。我修改了答案以显示一个示例。我最初将我的编辑作为答案发布,但觉得最好将其作为问题的更新。