Подтвердить что ты не робот

Импорт всего (*) динамически из модуля

У меня есть модуль Python, который я хочу динамически импортировать, учитывая только строку имени модуля. Обычно я использую importlib или __import__, и это работает достаточно хорошо, учитывая, что я знаю, какие объекты я хочу импортировать из модуля, но есть ли способ сделать эквивалент import * динамически. Или есть лучший подход?

Я знаю, что в целом его плохая практика заключается в использовании import *, но модули, которые я пытаюсь импортировать, автоматически генерируются "на лету", и я не могу точно знать точный модуль, который содержит класс, к которому я обращаюсь.

Спасибо.

4b9b3361

Ответ 1

Я придумал какой-то уродливый взломанный код, он работает в python 2.6. Я не уверен, что это самая умная вещь, хотя, возможно, некоторые другие люди здесь имеют некоторое представление:

test = __import__('os',globals(),locals())
for k in dir(test):
    globals()[k] = test.__dict__[k]

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

Например, скажем, что ваш класс называется Request from urllib2

test = __import__('urllib2',globals(),locals())
cls = None
if 'Request' in dir(test):
    cls = test.__dict__['Request']
    # you found the class now you can use it!
    cls('http://test.com')

Ответ 2

Используйте update для dicts:

globals().update(importlib.import_module('some.package').__dict__)

Обратите внимание, что использование a_module.__dict__ не совпадает с from a_module import *, потому что все имена импортируются не только из __all__, либо не начинаются с _.

Ответ 3

Следующее очень греховно и осудит вас в чистилище или хуже

# module A
myvar = "hello"

# module B
import inspect
def dyn_import_all(modpath):
  """Incredibly hackish way to load into caller global namespace"""
  exec('from ' + modpath + ' import *', inspect.stack()[1][0].f_globals)

# module C
from module B import dyn_import_all
def print_from(modpath):
  dyn_import_all(modpath)
  print(myvar)

Ответ 4

Единственный способ, которым я могу это сделать, - использовать exec() и динамически генерировать команду importlib на лету.