2008-10-17 40 views

Trả lời

52

Từ các tài liệu python trên __import__:

__import__(name[, globals[, locals[, fromlist[, level]]]]) 

...

Khi biến tên có dạng package.module, thông thường, các gói cấp cao nhất (các tên lên đến dấu chấm đầu tiên) được trả lại, không phải là mô-đun được đặt tên theo tên. Tuy nhiên, khi một đối số không được để trống , mô-đun được đặt tên theo tên được trả về. Điều này được thực hiện để tương thích với mã bytecode được tạo cho các loại báo cáo nhập khác nhau; khi sử dụng "import spam.ham.eggs", thư rác gói cấp cao nhất phải được đặt trong không gian tên nhập, nhưng khi sử dụng "từ spam.ham nhập trứng", thì phải sử dụng gói phụ spam.ham.ham.ham tới số tìm biến số trứng. Để giải quyết sự cố này, hãy sử dụng getattr() để trích xuất các thành phần mong muốn mong muốn. Ví dụ, bạn có thể xác định helper sau:

def my_import(name): 
    mod = __import__(name) 
    components = name.split('.') 
    for comp in components[1:]: 
     mod = getattr(mod, comp) 
    return mod 

Để diễn giải:

Khi bạn yêu cầu somepackage.somemodule, __import__ lợi nhuận somepackage.__init__.py, mà thường là rỗng.

Nó sẽ trở lại somemodule nếu bạn cung cấp fromlist (một danh sách các tên biến bên somemodule bạn muốn, mà không thực sự trả lại)

Bạn cũng có thể, như tôi đã làm, sử dụng chức năng họ đề nghị.

Lưu ý: Tôi đã hỏi câu hỏi này có ý định hoàn toàn để tự trả lời. Có một lỗi lớn trong mã của tôi, và đã chẩn đoán sai nó, nó đã cho tôi một thời gian dài để tìm ra nó, vì vậy tôi figured tôi sẽ giúp cộng đồng SO ra và đăng các gotcha tôi chạy vào đây.

7

Có một cái gì đó mà làm việc như bạn muốn nó: twisted.python.reflect.namedAny:

>>> from twisted.python.reflect import namedAny 
>>> namedAny("operator.eq") 
<built-in function eq> 
>>> namedAny("pysqlite2.dbapi2.connect") 
<built-in function connect> 
>>> namedAny("os") 
<module 'os' from '/usr/lib/python2.5/os.pyc'> 
+0

Đó là rất hữu ích, tuy nhiên tôi không thực sự có bất cứ nhu cầu khác cho xoắn trong chương trình của tôi. Mặc dù, với tư cách là người sáng lập (!), Bạn có thể hiểu biết nhiều về khả năng hơn tôi (không bao giờ sử dụng nó). – dwestbrook

32

python 2.7 có importlib, đường dẫn chấm giải quyết như mong đợi

import importlib 
foo = importlib.import_module('a.dotted.path') 
instance = foo.SomeClass() 
+2

Ngoài ra còn có một gói python 2.6 giúp backports chức năng này. https://pypi.python.org/pypi/importlib/ – melinath

1

Đối với python 2.6, tôi đã viết đoạn này:

def import_and_get_mod(str, parent_mod=None): 
    """Attempts to import the supplied string as a module. 
    Returns the module that was imported.""" 
    mods = str.split('.') 
    child_mod_str = '.'.join(mods[1:]) 
    if parent_mod is None: 
     if len(mods) > 1: 
      #First time this function is called; import the module 
      #__import__() will only return the top level module 
      return import_and_get_mod(child_mod_str, __import__(str)) 
     else: 
      return __import__(str) 
    else: 
     mod = getattr(parent_mod, mods[0]) 
     if len(mods) > 1: 
      #We're not yet at the intended module; drill down 
      return import_and_get_mod(child_mod_str, mod) 
     else: 
      return mod 
16

Có giải pháp đơn giản hơn, như được giải thích trong tài liệu:

Nếu bạn chỉ muốn nhập mô-đun (có khả năng trong một gói) theo tên, bạn có thể gọi __import __() và sau đó tìm kiếm trong sys.module:

>>> import sys 
>>> name = 'foo.bar.baz' 
>>> __import__(name) 
<module 'foo' from ...> 
>>> baz = sys.modules[name] 
>>> baz 
<module 'foo.bar.baz' from ...> 
0

Con đường tôi đã làm là

foo = __import__('foo', globals(), locals(), ["bar"], -1) 
foobar = eval("foo.bar") 

sau đó tôi có thể truy cập bất kỳ nội dung từ bằng cách

foobar.functionName() 
+1

Tại sao không chỉ, 'foo.bar' vào thời điểm đó? –

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