У меня есть строка, сказать: abc.def.ghi.jkl.myfile.mymethod
. Как мне динамически импортировать mymethod
?
Вот как я это сделал:
def get_method_from_file(full_path):
if len(full_path) == 1:
return map(__import__,[full_path[0]])[0]
return getattr(get_method_from_file(full_path[:-1]),full_path[-1])
if __name__=='__main__':
print get_method_from_file('abc.def.ghi.jkl.myfile.mymethod'.split('.'))
Мне интересно, требуется ли вообще импорт отдельных модулей.
Изменить: я использую Python версии 2.6.5.
python
dynamic
import
dynamic-import
Лакшман Прасад
источник
источник
importlib.import_module()
over__import__()
: docs.python.org/2/library/functions.html#__import__ - для 2.7+.import_module
+rsplit
= Единственный верный путь.Вам не нужно импортировать отдельные модули. Достаточно импортировать модуль, из которого вы хотите импортировать имя, и указать
fromlist
аргумент:def import_from(module, name): module = __import__(module, fromlist=[name]) return getattr(module, name)
Для вашего примера
abc.def.ghi.jkl.myfile.mymethod
вызовите эту функцию какimport_from("abc.def.ghi.jkl.myfile", "mymethod")
(Обратите внимание, что в Python функции уровня модуля называются функциями, а не методами.)
Для такой простой задачи нет преимущества в использовании
importlib
модуля.источник
myClass = getattr(__import__("module.to.import", fromlist=["myClassName"]), "myClassName")
. Спасибо за помощь!__import__
Подход делает работу. Но попробуйте бежатьhelp(__import__)
. В нем говорится: «Поскольку эта функция предназначена для использования интерпретатором Python, а не для общего использования, ее лучше использоватьimportlib.import_module()
для программного импорта модуля».importlib
вместо этого.Для Python <2.7 можно использовать встроенный метод __ import__ :
__import__('abc.def.ghi.jkl.myfile.mymethod', fromlist=[''])
Для Python> = 2.7 или 3.1 добавлен удобный метод importlib.import_module . Просто импортируйте свой модуль следующим образом:
importlib.import_module('abc.def.ghi.jkl.myfile.mymethod')
Обновление : обновленная версия в соответствии с комментариями ( я должен признать, что не прочитал импортируемую строку до конца, и я пропустил тот факт, что должен быть импортирован метод модуля, а не сам модуль) :
Python <2.7:
mymethod = getattr(__import__("abc.def.ghi.jkl.myfile", fromlist=["mymethod"]))
Python> = 2.7:
mymethod = getattr(importlib.import_module("abc.def.ghi.jkl.myfile"), "mymethod")
источник
__import__()
иimportlib.import_module()
.Непонятно, что вы пытаетесь сделать со своим локальным пространством имен. Полагаю, вы хотите,
my_method
как местный житель, печататьoutput = my_method()
?# This is equivalent to "from a.b.myfile import my_method" the_module = importlib.import_module("a.b.myfile") same_module = __import__("a.b.myfile") # import_module() and __input__() only return modules my_method = getattr(the_module, "my_method") # or, more concisely, my_method = getattr(__import__("a.b.myfile"), "my_method") output = my_method()
Хотя вы только добавляете
my_method
в локальное пространство имен, вы загружаете цепочку модулей. Вы можете просмотреть изменения, просмотрев ключиsys.modules
до и после импорта. Я надеюсь, что это яснее и точнее, чем другие ваши ответы.Для полноты, вот как вы добавляете всю цепочку.
# This is equivalent to "import a.b.myfile" a = __import__("a.b.myfile") also_a = importlib.import_module("a.b.myfile") output = a.b.myfile.my_method() # This is equivalent to "from a.b import myfile" myfile = __import__("a.b.myfile", fromlist="a.b") also_myfile = importlib.import_module("a.b.myfile", "a.b") output = myfile.my_method()
И, наконец, если вы используете
__import__()
и изменили свой путь поиска после запуска программы, вам может потребоваться использовать__import__(normal args, globals=globals(), locals=locals())
. Почему - сложное обсуждение.источник
the_module
иsame_module
не так , и дают разные результаты. Голосование против.from importlib import import_module name = "file.py".strip('.py') # if Path like : "path/python/file.py" # use name.replaces("/",".") imp = import_module(name) # get Class From File.py model = getattr(imp, "classNameImportFromFile") NClass = model() # Class From file
источник
.strip()
ведет себя правильно в том случае, о котором вы заявили. В частности, если файл начинается с «py», эти символы также будут удалены. Например,"pyfile.py".strip(".py")
производит там"file"
, где было бы предпочтительнее производить"pyfile"
в этом случае.name.replace(".py","")
хотя работает нормально.У этого веб-сайта есть хорошее решение: load_class . Я использую это так:
foo = load_class(package.subpackage.FooClass)() type(foo) # returns FooClass
По запросу, вот код из веб-ссылки:
import importlib def load_class(full_class_string): """ dynamically load a class from a string """ class_data = full_class_string.split(".") module_path = ".".join(class_data[:-1]) class_str = class_data[-1] module = importlib.import_module(module_path) # Finally, we retrieve the Class return getattr(module, class_str)
источник
Используйте
importlib
(только 2.7+).источник
from __future__
?__future__
это для языковых функций, а не для новых модулей stdlib.__import__
как в примерах выше. Он работает до версии 2.5 и без ключевых слов до этого.Способ, которым я склоняюсь к этому (а также ряд других библиотек, таких как pylons и paste, если моя память мне не изменяет), состоит в том, чтобы отделить имя модуля от имени функции / атрибута, используя ':' между ними . См. Следующий пример:
'abc.def.ghi.jkl.myfile:mymethod'
Это упрощает использование
import_from(path)
приведенной ниже функции.def import_from(path): """ Import an attribute, function or class from a module. :attr path: A path descriptor in the form of 'pkg.module.submodule:attribute' :type path: str """ path_parts = path.split(':') if len(path_parts) < 2: raise ImportError("path must be in the form of pkg.module.submodule:attribute") module = __import__(path_parts[0], fromlist=path_parts[1]) return getattr(module, path_parts[1]) if __name__=='__main__': func = import_from('a.b.c.d.myfile:mymethod') func()
источник
Как насчет этого :
def import_module(name): mod = __import__(name) for s in name.split('.')[1:]: mod = getattr(mod, s) return mod
источник