Import a shared library and global namespace

I am trying to import a shared library that contains several Python wrappers for a visualization program ( VisIt ). This library is implemented in such a way that the library is imported first, which makes several functions available, and then you call the function that launches the visualisaion viewer and makes the rest of the API available for calling. For example, in the following

form visit import * print dir() Launch() print dir() 

the first print statement contains the usual built-in functions and a couple of other functions

 ['AddArgument', 'GetDebugLevel', 'Launch', 'SetDebugLevel', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__warningregistry__'] 

and the second print output

 ['ActivateDatabase', 'AddArgument', 'AddColorTable', 'AddOperator', 'AddPlot', ... ] 

and etc.

I want instead to call Launch inside the function (so I can process and pass arguments to Launch ). However, when I do this, the functions that become available after Launch called are not in the global namespace, but in the namespace local to the function. So in the following example

 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) 

The print statement in main will print

 ['ActivateDatabase', 'AddArgument', 'AddColorTable', 'AddOperator', 'AddPlot', ... ] 

as indicated above, whereas print immediately after main is called prints

 ['AddArgument', 'GetDebugLevel', 'Launch', 'SetDebugLevel', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__warningregistry__'] 

as if Launch never called.

My first question is: how to ensure that the global namespace is populated with a Launch call?

Secondly, the Version call actually fails

NameError: global name "Version" not defined

although print "Version" in dir() returns True . Will this problem be solved if I solve my first problem or is it something else?

Please let me know if you need more information on the shared library. I donโ€™t know much about how it is written, but I can try to find out.

Edit: Following @voithos's answer, the next solution I made.

As pointed out by @voithos, "Visit uses dynamic imports, which brings everything to the local scope ... provided that you never call visit.Launch() outside the global scope." His (initial) answer allows me to make the functions available in visit.Launch() for use outside (and inside) of my main routine using the visit. prefix visit. with all of these routines.

To import VisIt routines as from visit import * so that they can be called without the visit. prefix visit. I change the use of @voithos setattr in main as follows

 # 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]) 

then VisIt procedures are available at the module level and everything seems to be fine.

Thanks @voithos for your answer.

+4
source share
2 answers

Visit seems to be using dynamic imports, which brings everything to the local area. Basically, they assume that you will never call visit.Launch() outside the global scope. The launch function is written in C ++, so I'm not sure exactly how it is imported.

One way is to reassign names from the local area to another area. (for example, in the visit module that you import) Here is an example:

 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) 

If you want to name the global scope, you can change the loop:

 loc = locals() glob = globals() for key in loc: glob[key] = loc[key] 
However, note: doing this will overwrite any conflicting character names that you defined earlier. For example, if you defined the Version() function, Version() from the Visit module will overwrite the older one that you defined. Therefore, in general, itโ€™s a good idea not to clutter up the global scope with names unless you really need to.
+2
source

I have never used VisIt, but according to their documentation you need to do:

 import visit def main(): visit.Launch() 

which will import all functions into the "visit" namespace. Then you simply interact with the library function through the visit namespace. How in:

 visit.Version() 
0
source

Source: https://habr.com/ru/post/1384217/


All Articles