2012-01-11 4 views
0

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

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 ....

ответ

0

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

Кроме того, синтаксис «import module as othername» - это просто способ объединения объекта модуля с другой переменной.

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

import module 
othername = module 
del module 

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

Вместо прохождения: guessedname.run()

попытка прохождения:

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

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

+0

Спасибо, это гораздо лучшее решение, чем использование фреймов! – Jordan

1

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

import some.plugin as wanna_have 

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

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

+0

Это не «the_only_ way this can _ever_ work» - у python достаточно интроспекции, чтобы разрешить что-либо по линиям, которые запросит OP, но требуя явного init звонок в этом случае очень чистый, действительно. – jsbueno

0

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

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

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

Я пробовал с

import numpy as np 

Тогда я применил Oneliner я упоминал выше:

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

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

Local module name is np 
+0

tis не поможет - ему не нужно найти имя модуля в модуле, на котором запущен его код, - он должен найти свое имя в модуле, написанном третьим лицом, которое импортирует его модуль – jsbueno

+0

@jsbueno спасибо, приятно знать –

Смежные вопросы