2011-01-27 24 views
101

Trong python, tôi phải khởi tạo lớp nhất định, biết tên của nó trong một chuỗi, nhưng lớp này 'sống' trong mô-đun được nhập động. Một ví dụ sau:Triết lý động Python từ tên chuỗi của một lớp trong mô-đun được nhập động

loader-lớp kịch bản:

import sys 
class loader: 
    def __init__(self, module_name, class_name): # both args are strings 
    try: 
     __import__(module_name) 
     modul = sys.modules[module_name] 
     instance = modul.class_name() # obviously this doesn't works, here is my main problem! 
    except ImportError: 
     # manage import error 

số-động-nạp-mô-đun kịch bản:

class myName: 
    # etc... 

tôi sử dụng sự sắp xếp này để thực hiện bất kỳ động nạp module được được sử dụng bởi lớp trình tải theo các hành vi nhất định được xác định trước trong các mô-đun dyn-loaded ...

Bất kỳ ý tưởng nào được đánh giá cao.

Trả lời

149

Bạn có thể sử dụng getattr

getattr(module, class_name) 

để truy cập lớp. mã hoàn chỉnh hơn:

module = __import__(module_name) 
class_ = getattr(module, class_name) 
instance = class_() 

Như đã đề cập below, chúng tôi có thể sử dụng importlib

import importlib 
module = importlib.import_module(module_name) 
class_ = getattr(module, class_name) 
instance = class_() 
+3

'module = __import __ (mô đun, fromlist = [name])' chỉ làm việc cho tôi. – umpirsky

+15

Nếu bất kỳ ai gặp sự cố với phương thức nhập Sven đã đề cập ở trên, tôi thấy mã của tôi hoạt động tốt hơn bằng cách sử dụng phương thức sau thay vì [importlib.import_module] (http://docs.python.org/2/library/importlib.html#importlib .import_module). Có thể được sử dụng như: module = importlib.import_module (module_name) – jpennell

+0

@jpennell bạn nên đăng câu trả lời đó, thường hữu ích hơn khi có thể trực tiếp sử dụng chuỗi được trả về bởi 'obj .__ module__' – Anentropic

11

Sử dụng getattr để có được một thuộc tính từ một tên trong một chuỗi. Nói cách khác, lấy ví dụ như đoạn

instance = getattr(modul, class_name)() 
9

Sao chép-dán:

def str_to_class(module_name, class_name) 
    try: 
     module_ = importlib.import_module(module_name) 
     try: 
      class_ = getattr(module_, class_name)() 
     except AttributeError: 
      logging.error('Class does not exist') 
    except ImportError: 
     logging.error('Module does not exist') 
    return class_ or None 
5

Nếu bạn muốn câu này from foo.bar import foo2 được nạp tự động, bạn nên làm điều này

foo = __import__("foo") 
bar = getattr(foo,"bar") 
foo2 = getattr(bar,"foo2") 

instance = foo2() 
2

tôi không thể đạt được điều đó trong trường hợp sử dụng của tôi từ các ví dụ trên, nhưng Ahmad đã cho tôi gần nhất (cảm ơn). Đối với những người đọc điều này trong tương lai, đây là mã làm việc cho tôi.

def get_class(fully_qualified_path, module_name, class_name, *instantiation): 
    """ 
    Returns an instantiated class for the given string descriptors 
    :param fully_qualified_path: The path to the module eg("Utilities.Printer") 
    :param module_name: The module name eg("Printer") 
    :param class_name: The class name eg("ScreenPrinter") 
    :param instantiation: Any fields required to instantiate the class 
    :return: An instance of the class 
    """ 
    p = __import__(fully_qualified_path) 
    m = getattr(p, module_name) 
    c = getattr(m, class_name) 
    instance = c(*instantiation) 
    return instance 
84

tl; dr

nhập các mô-đun với importlib.import_module và tải các lớp học mà bạn cần với getattr:

# Standard import 
import importlib 
# Load "module.submodule.MyClass" 
MyClass = getattr(importlib.import_module("module.submodule"), "MyClass") 
# Instantiate the class (pass arguments to the constructor, if needed) 
instance = MyClass() 

giải thích

Bạn có lẽ không muốn sử dụng __import__ để tự động nhập mô-đun theo tên, vì nó không cho phép bạn nhập mô-đun con:

>>> mod = __import__("os.path") 
>>> mod.join 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'module' object has no attribute 'join' 

Here là những gì trăn doc nói về __import__:

Note: This is an advanced function that is not needed in everyday Python programming, unlike importlib.import_module().

Thay vào đó, sử dụng các mô-đun importlib tiêu chuẩn để tự động nhập khẩu một module theo tên.Với getattr sau đó bạn có thể nhanh chóng một lớp theo tên của nó:

import importlib 
my_module = importlib.import_module("module.submodule") 
MyClass = getattr(my_module, "MyClass") 
instance = MyClass() 

Bạn cũng có thể viết:

import importlib 
module_name, class_name = "module.submodule.MyClass".rsplit(".", 1) 
MyClass = getattr(importlib.import_module(module_name), class_name) 
instance = MyClass() 

Mã này là hợp lệ trong python ≥ 2.7 (bao gồm python 3).

+0

có thể tôi không hiểu câu trả lời của bạn, nhưng tôi đã sử dụng __import__ để nhập mô-đun con: __import __ (" module. "+ submodule_name_string) –

+0

Đoạn mã sau dẫn đến một AttributeError: 'mod = __import __ (" os.path "); mod.join' trong khi sau không: 'mod = importlib.import_module (" os.path "); mod.join' –

+0

oh Tôi hiểu, bạn nói đúng nhưng tôi đã làm như sau để có được phương pháp os.path.join: getattr (sys.modules ["os.path"], "tham gia") –

Các vấn đề liên quan