2010-02-25 7 views
1

Я знаю, что это не звучит Pythonic, но медведь со мной на секунду.Как я могу выяснить в своем модуле, если основная программа использует определенную переменную?

Я пишу модуль, который зависит от какого-либо внешнего модуля с закрытым кодом. Этот модуль должен получить экземпляр для использования (используя module.create()).

Мой модуль пытается выяснить, действительно ли мой пользователь уже загрузил этот модуль (легко сделать), но затем необходимо выяснить, был ли экземпляр модуля. Я понимаю, что проверка типа() каждой переменной может мне это сказать, но я не уверен, как я могу получить имена переменных, определенных основной программой. Причина этого заключается в том, что при создании экземпляра модели они также устанавливают набор параметров, которые я не хочу переписывать по какой-либо причине.

Мои попытки до сих пор были связаны с использованием sys._getframe(). F_globals и итерацией по элементам, но в моем тестировании это не работает. Если я создам экземпляр модуля как modInst, а затем вызову функцию в моем модуле, он не сможет показать переменную modInst. Есть ли другое решение? Пример кода приведен ниже.

import sys 
if moduleName not in sys.modules: 
    import moduleName 
    modInst = moduleName.create() 
else: 
    globalVars = sys._getframe().f_globals 
    for key, value in globalVars: 
     if value == "Module Name Instance": 
      return key 
    return moduleName.create() 

EDIT: пример кода.

ответ

1

Похоже, ваш код предполагает, что функция .create() называлась, если вообще, немедленным/прямой вызывающему вашей функции (которые вы показываете только частично, что делает его довольно трудно быть уверенным в том, что происходит) и результаты, помещенные в global переменная (модуля, в котором находится вызывающая функция вашей функции). Все это кажется довольно хрупким. Не имеет ли в стороннем модуле какие-либо собственные глобальные переменные, на которые влияет то, вызвано ли имя модуля create? Я предполагаю, что это будет - где еще он будет сохранять изменения состояния в результате выполнения create - и я бы изучил это.

Для решения конкретной проблемы вы поднимаете,

Я не знаю, как я могу получить имена переменных, определяемых основной программы

, который легко - основная программа найден как модуль в sys.modules['__main__'], поэтому просто используйте vars(sys.modules['__main__']), чтобы получить глобальный словарь основной программы (имена переменных - это ключи в этом словаре, а вместе с именами функций, классов и т. д. - модуль, как и любой другой модуль, имеет ровно один пространство верхнего уровня/глобального пространства имен, а не одно для переменных, отдельное для функций и т. Д.).

+0

Alex, спасибо. Sys.modules ['__ main__'] намного более элегантны, чем sys._getframe (1) .f_globals. Конечно, они оба предполагают, что основная программа - это функция, называемая функцией create, а не один из их собственных модулей, но я не уверен, что это легко решить (если только я не пересекаю все sys.modules). Что касается функции .create(), создающей любые переменные - это не так. Все переменные хранятся в объекте create(), создающем для вас, и ничего не хранится снаружи. Вот почему у меня так много проблем с этим. Есть ли способ найти объект независимо от модуля? –

+0

@ Michalis, вообще говоря, нет, нет общего способа найти объект, не имея представления о том, где он может быть сохранен. Однако вы можете попробовать http://docs.python.org/library/gc.html?highlight=gc#gc.get_objects - он вернет вам все списки и dicts (и некоторые другие контейнеры) для вас. Разумеется, для большой программы эта проверка может занять довольно много времени! –

0

Предположим, что внешний модуль с закрытым источником называется extmod. Создание my_extmod.py:

import extmod 
INSTANTIATED=False 
def create(*args,**kw): 
    global INSTANTIATED 
    INSTANTIATED=True 
    return extmod.create(*args,**kw) 

Затем требуется пользователям импортировать my_extmod вместо extmod непосредственно. Чтобы проверить, была ли вызвана функция create, просто проверьте значение extmod.INSTANTIATED.

Edit: Если открыть сеанс IPython и тип import extmod, затем введите extmod.[TAB], то вы будете видеть все переменные верхнего уровня в extmod пространстве имен. Это может помочь вам найти какой-то параметр, который изменяется при вызове extmod.create.

Запрет на то, чтобы запретить обучение пользователей для импорта my_extmod, возможно, вы могли бы использовать что-то вроде функции ниже. find_extmod_instance выполняет поиск по всем модулям в sys.modules.

def find_instance(cls): 
    for modname in sys.modules: 
     module=sys.modules[modname] 
     for value in vars(module).values(): 
      if isinstance(value,cls): 
       return value 

x=find_instance(extmod.ExtmodClass) or extmod.create() 
+0

unutbu, Именно так я и думал, но я понял, что мне нужен способ убедиться, что, если мои пользователи не следуют инструкциям (которые, как я считаю, почти всегда имеют место), я не стираю их работа. Вот почему мне нужно знать, создавали ли они это сами или нет. Конечно, если это невозможно, мне нужно выяснить другой способ убедиться, что они не обманывают слишком много. –

+0

@Michalis: Хорошо, вот еще одна мысль: вы упомянули, что есть ряд параметров, которые вы не хотите перезаписывать. Можете ли вы узнать, какие значения по умолчанию этих параметров (или если они существуют), а затем сравнить их с их текущими значениями? Если другое, то вы знаете, что пользователь должен был вызвать 'create' ...? – unutbu

+0

Да, я мог бы. Но все эти параметры доступны через экземпляр объекта, который я пытаюсь найти. Поэтому мне все же нужно найти, было ли оно создано и какое имя оно использует. –

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

  • Нет связанных вопросов^_^