nhập mô-đun từ biến chuỗi


183

Tôi đang làm việc trên một tài liệu (cá nhân) cho thư viện matplotlib (MPL) lồng nhau, khác với MPL được cung cấp bởi các gói mô hình con quan tâm. Tôi đang viết tập lệnh Python mà tôi hy vọng sẽ tự động tạo tài liệu từ các bản phát hành MPL trong tương lai.
Tôi đã chọn các gói / gói con quan tâm và muốn liệt kê các lớp chính của chúng mà tôi sẽ tạo danh sách và xử lý nó vớipydoc

Vấn đề là tôi không thể tìm cách hướng dẫn Python tải mô hình con từ chuỗi. Đây là ví dụ về những gì tôi đã thử:

import matplotlib.text as text
x = dir(text)

.

i = __import__('matplotlib.text')
y = dir(i)

.

j = __import__('matplotlib')
z = dir(j)

Và đây là 3 cách so sánh các danh sách trên thông qua pprint:

nhập mô tả hình ảnh ở đây

Tôi không hiểu những gì được tải trong yđối tượng - đó là cơ sở matplotlibcộng với thứ khác, nhưng nó thiếu thông tin mà tôi muốn và đó là các lớp chính từ matplotlib.textgói. Đó là phần màu xanh hàng đầu trên ảnh chụp màn hình ( xdanh sách)

Xin đừng đề nghị Nhân sư như cách tiếp cận khác.


Bạn có thể giải thích lý do tại sao bạn cần sử dụng __import__(str)chứ không phải là tiêu chuẩn importstHRetn?
từ

Đó là vì tôi sẽ xử lý danh sách các mục nào là mô đun con MPL và nhận đường dẫn phương thức của chúng
theta

9
@thesamet - C'mon - có những ý tưởng bất tận mà bạn muốn chức năng này. Khi bạn có một cấu hình văn bản của các thư viện, bạn có thể tải chúng theo tên, điều này sẽ không hoạt động với importcâu lệnh. Đây là một ví dụ về việc sử dụng: djangosnippets.org/snippets/3048
Tomasz Gandor

Câu trả lời:


279

Các __import__chức năng có thể là một chút khó hiểu.

Nếu bạn thay đổi

i = __import__('matplotlib.text')

đến

i = __import__('matplotlib.text', fromlist=[''])

sau đó isẽ tham khảo matplotlib.text.

Trong Python 2.7 và Python 3.1 trở lên, bạn có thể sử dụng importlib:

import importlib

i = importlib.import_module("matplotlib.text")

Một số lưu ý

  • Nếu bạn đang cố nhập một cái gì đó từ thư mục con ./feature/email.py, vd , mã sẽ trông nhưimportlib.import_module("feature.email")

  • Bạn không thể nhập bất cứ thứ gì nếu không có __init__.pytrong thư mục chứa tệp bạn đang cố nhập


3
importlibnên có sẵn trên pypi cho <python2.7
Jeffrey Jose

50
Đối với bất cứ ai đến đây từ Google. Cần lưu ý rằng nếu bạn đang cố gắng nhập một cái gì đó từ một thư mục con (ví dụ ./feature/email.py), mã sẽ trông như thếimportlib.import_module("feature.email")
Seanny123

11
Cuối cùng, hãy nhớ rằng bạn không thể nhập bất cứ thứ gì nếu không có __init__.pytrong thư mục chứa tệp bạn đang cố gắng nhập.
Seanny123

3
@mzjn Đây là import moduleNamenơi mà moduleName là chuỗi. Thế còn from moduleName import *?
Nam G VU

2
Chỉ cần tìm câu trả lời cho câu hỏi của tôi ở đây trong trường hợp bất kỳ ai cần nó stackoverflow.com/a/31306598/248616
Nam G VU

68

importlib.import_modulelà những gì bạn đang tìm kiếm. Nó trả về các mô-đun nhập khẩu. (Chỉ khả dụng cho Python> = 2.7 hoặc 3.x):

import importlib

mymodule = importlib.import_module('matplotlib.text')

Sau đó, bạn có thể truy cập bất cứ thứ gì trong mô-đun như mymodule.myclass, v.v.


Một cách khác là imp.load_source(..)sử dụng impmô-đun như được đề xuất trong câu trả lời này stackoverflow.com/questions/67631/NH
Evgeni Sergeev

5
@gecco Đây là import moduleNamenơi mà moduleName là chuỗi. Thế còn from moduleName import *?
Nam G VU

6

đã dành một chút thời gian để cố gắng nhập các mô-đun từ một danh sách và đây là chủ đề giúp tôi đi gần hết - nhưng tôi không nắm bắt được việc sử dụng ___import__ -

Vì vậy, đây là cách nhập mô-đun từ một chuỗi và có hành vi tương tự như chỉ nhập. Và thử / ngoại trừ trường hợp lỗi, quá. :)

  pipmodules = ['pycurl', 'ansible', 'bad_module_no_beer']
  for module in pipmodules:
      try:
          # because we want to import using a variable, do it this way
          module_obj = __import__(module)
          # create a global object containging our module
          globals()[module] = module_obj
      except ImportError:
          sys.stderr.write("ERROR: missing python module: " + module + "\n")
          sys.exit(1)

và có, đối với python 2.7> bạn có các tùy chọn khác - nhưng với 2.6 <, điều này hoạt động.


1

Tôi đã phát triển 3 chức năng hữu ích này:

def loadModule(moduleName):
    module = None
    try:
        import sys
        del sys.modules[moduleName]
    except BaseException as err:
        pass
    try:
        import importlib
        module = importlib.import_module(moduleName)
    except BaseException as err:
        serr = str(err)
        print("Error to load the module '" + moduleName + "': " + serr)
    return module

def reloadModule(moduleName):
    module = loadModule(moduleName)
    moduleName, modulePath = str(module).replace("' from '", "||").replace("<module '", '').replace("'>", '').split("||")
    if (modulePath.endswith(".pyc")):
        import os
        os.remove(modulePath)
        module = loadModule(moduleName)
    return module

def getInstance(moduleName, param1, param2, param3):
    module = reloadModule(moduleName)
    instance = eval("module." + moduleName + "(param1, param2, param3)")
    return instance

Và mỗi khi tôi muốn tải lại một cá thể mới, tôi chỉ cần gọi getInstance () như thế này:

myInstance = getInstance("MyModule", myParam1, myParam2, myParam3)

Cuối cùng tôi có thể gọi tất cả các chức năng bên trong Instance mới:

myInstance.aFunction()

Tính cụ thể duy nhất ở đây là tùy chỉnh danh sách params (param1, param2, param3) của cá thể bạn.


1

Ngoài việc sử dụng, người importlibta cũng có thể sử dụng execphương thức để nhập mô-đun từ biến chuỗi.

Ở đây tôi trình bày một ví dụ về nhập combinationsphương thức từ itertoolsgói bằng execphương thức:

MODULES = [
    ['itertools','combinations'],
]

for ITEM in MODULES:
    import_str = "from {0} import {1}".format(ITEM[0],', '.join(str(i) for i in ITEM[1:]))
    exec(import_str)

ar = list(combinations([1, 2, 3, 4], 2))
for elements in ar:
    print(elements)

Đầu ra:

(1, 2)
(1, 3)
(1, 4)
(2, 3)
(2, 4)
(3, 4)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.