Нахождение локального имени модуля из этого модуля - PullRequest
0 голосов
/ 12 января 2012

Я пытаюсь получить точное имя модуля, с которым был импортирован модуль, из этого модуля.Примерно так:

def install():
    print 'Local module name is %s' % __localModuleName__

И когда я запустил:

import myModule as mm
mm.install()

Будет напечатано

Local module name is mm

Скрипт, который я пытаюсь сделать, устанавливает себя ввнешнее приложение майя.Maya оценивает строку, которую я передаю по требованию в python.Прямо сейчас я пытаюсь дать Майе строку "myModule.run()".В этом случае мне нужно знать точное имя myModule при первом запуске myModule.install().__name__ недостаточно конкретно, если пользователь импортирует модуль, используя import myModule as otherModule.

Если есть лучший способ сделать это, не связанный с использованием точного имени модуля, я бы хотел знать.Как-то конвертировать ссылку myModule.run в строку, которую я мог хранить в Maya, а затем распаковать.Я пытался использовать модуль inspect, чтобы найти эту информацию, но я продолжаю находить ситуации, когда она не работает, и мне приходится возвращаться и возиться с ней еще немного.Это также кажется немного грязным.Это то, что я использую прямо сейчас, и это не работает, если myModule вызывается с __main__.

MODULENAME = None
fr = inspect.currentframe()
try:
    while fr and not MODULENAME:
        if fr.f_globals:
            for name, obj in fr.f_globals.iteritems():
                if hasattr(obj, '__file__') and inspect.ismodule(obj) and obj.__file__ == __file__:
                    MODULENAME = name
        fr = fr.f_back
except:
    pass
finally:
    del fr

Если не существует хорошего решения, я планирую удалить приведенное выше и сообщитьпользователи, которые не могут импортировать мой модуль, используя import myModule as ....

Ответы [ 3 ]

1 голос
/ 12 января 2012

Единственный способ, которым это когда-либо может работать, - это:

import some.plugin as wanna_have

wanna_have.install(globals(), "wanna_have")

Почему это так?Вам нужно и пространство имен импортирующего модуля и импортируемого модуля здесь, и первое требует, чтобы вы передали globals ().Единственный способ предотвратить это - перейти на up один стек в методе install (), предполагая, что вызывающий код - это имя с псевдонимом.Когда вы используете подпись install(importer=None, imported=__name__), необходимость передавать все эти вещи может быть сведена к случаям, когда используется «как», или вызывающий абонент не на один кадр вверх.

0 голосов
/ 12 января 2012

Подход, близкий к тому, который вы пробуете, должен сработать - но он будет сложен, как вы могли бы проверить.

Более того, синтаксис «импортировать модуль как другое имя» - это просто обычный способ связывания модуляОбъект другой переменной.

Это просто эквивалент

import module
othername = module
del module

И ваш код не должен зависеть от этого для запуска.Однако в глобальном словаре sys.modules ваш модуль всегда отображается с его «настоящим» именем.Поэтому, если вы можете передать выражение в строке в хост-приложение, вы должны попытаться получить доступ к вашему модулю в этом словаре - гораздо менее запутанно.

Вместо передачи: guessedname.run()

попробуйте передать:

__import__("sys").modules["<module_name>"].run()

И не обращайте внимания на имя переменной, которая ссылается на ваш модуль в работающем коде.(это даже позволит пользователю сделать from module import * для вашего кода.

0 голосов
/ 12 января 2012

Я предлагаю следующее решение:

print 'Local module name is %s'%[key for key in vars() if 'myModule' in str(vars()[key])][0]

[0] - это на тот случай, если ваш модуль был импортирован несколько раз под разными именами, а вы просто выбрали первое.Если ваш модуль не был импортирован, вы получаете «IndexError: list index out of range», который, я полагаю, вы можете обработать самостоятельно.

Я попробовал его с

import numpy as np

Затем яприменил вышеупомянутый лайнер:

print 'Local module name is %s',[key for key in vars() if 'numpy' in str(vars()[key])][0]

и получу в результате:

Local module name is np
...