Импорт общей библиотеки и глобального пространства имен - PullRequest
4 голосов
/ 02 декабря 2011

Я пытаюсь импортировать разделяемую библиотеку, которая содержит несколько оболочек Python для программы визуализации (конкретнее VisIt ).Эта библиотека реализована таким образом, что сначала импортируется библиотека, которая делает доступными несколько функций, а затем вы вызываете функцию, которая запускает средство визуализации и делает доступным для вызова остальную часть 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)

оператор print в main будет печатать

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

, как указано выше, тогда как print сразу после main называется print

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

, как если бы Launch никогда не вызывалось.

Мой первый вопрос: как мне убедиться, что глобальное пространство имен заполняется вызовом Launch?

Во-вторых, вызов Version фактически завершается с ошибкой

NameError: глобальное имя 'Version' не определено

, даже если print "Version" in dir() возвращаетTrue.Будет ли эта проблема решена, если я решу свою первую проблему, или это что-то совсем другое?

Пожалуйста, дайте мне знать, если вам нужно больше информации над общей библиотекой.Я не знаю много о том, как это написано, но я могу попытаться выяснить.

Редактировать: После ответа @voithos, вот решение, которое я принял.

Как заявляет @voithos, «Visit использует динамический импорт, который переносит все в локальную область ... при условии, что вы никогда не вызовете visit.Launch() вне глобальной области».Его (первоначальный) ответ позволяет мне сделать функции, предоставляемые visit.Launch(), доступными вне (и внутри) моей основной подпрограммы, используя префикс visit. со всеми этими подпрограммами.

Чтобы импортироватьПроцедуры VisIt как from visit import *, так что они могут быть вызваны без префикса visit.. Я изменяю использование @voithos setattr в main на следующие

# 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 за ваш ответ.

Ответы [ 2 ]

2 голосов
/ 02 декабря 2011

Кажется, что Визит использует динамический импорт, который переносит все в локальную область.По сути, они предполагают, что вы никогда не вызовете visit.Launch() за пределами глобальной области видимости.Функция запуска полностью написана на C ++, поэтому я не уверен, как именно она импортируется.

Один из способов - переназначить имена из локальной области в другую область.(например, в модуль visit, который вы импортируете) Вот пример:

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() из модуля Visit перезапишет старую, которую вы определили.Следовательно, как правило, рекомендуется не загромождать глобальную область имен именами, если только вам это не нужно.

0 голосов
/ 02 декабря 2011

Я никогда не использовал VisIt, но в соответствии с их документацией вам нужно сделать:

import visit

def main():    
    visit.Launch()

, которая будет импортировать все функции в пространство имен 'visit'.Затем вы просто взаимодействуете с функцией библиотеки через пространство имен посещения.Как в:

visit.Version()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...