modul impor dari variabel string

183

Saya sedang mengerjakan dokumentasi (pribadi) untuk perpustakaan nested matplotlib (MPL), yang berbeda dari MPL sendiri yang disediakan, oleh paket submodule yang tertarik. Saya sedang menulis skrip Python yang saya harap akan mengotomatisasi pembuatan dokumen dari rilis MPL mendatang.
Saya memilih submodula / paket yang tertarik dan ingin mendaftar kelas utama mereka dari mana saya akan menghasilkan daftar dan memprosesnyapydoc

Masalahnya adalah bahwa saya tidak dapat menemukan cara untuk menginstruksikan Python untuk memuat submodule dari string. Ini adalah contoh dari apa yang saya coba:

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

.

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

.

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

Dan berikut adalah perbandingan 3 cara daftar di atas melalui sidik jari:

masukkan deskripsi gambar di sini

Saya tidak mengerti apa yang dimuat di yobjek - itu basis matplotlibditambah sesuatu yang lain, tetapi tidak memiliki informasi yang saya inginkan dan itu adalah kelas utama dari matplotlib.textpaket. Bagian berwarna biru teratas pada tangkapan layar (x daftar)

Tolong jangan menyarankan Sphinx sebagai pendekatan yang berbeda.

theta
sumber
Bisakah Anda menjelaskan mengapa Anda perlu menggunakan statemetn __import__(str)daripada standar import?
thesamet
Itu karena saya akan memproses daftar item mana yang merupakan submodul MPL dan mendapatkan jalur metode mereka
theta
9
@thesamet - ayolah - ada banyak ide di mana Anda menginginkan fungsi ini. Saat Anda memiliki konfigurasi teks pustaka, Anda dapat memuatnya dengan nama, yang tidak akan bekerja dengan importpernyataan tersebut. Inilah salah satu contoh penggunaan: djangosnippets.org/snippets/3048
Tomasz

Jawaban:

279

The __import__Fungsi dapat sedikit sulit untuk memahami.

Jika Anda berubah

i = __import__('matplotlib.text')

untuk

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

kemudian iakan merujuk kematplotlib.text .

Di Python 2.7 dan Python 3.1 atau yang lebih baru, Anda bisa menggunakan importlib:

import importlib

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

Beberapa catatan

  • Jika Anda mencoba mengimpor sesuatu dari sub-folder misalnya ./feature/email.py, kodenya akan terlihat sepertiimportlib.import_module("feature.email")

  • Anda tidak dapat mengimpor apa pun jika tidak ada __init__.pydalam folder dengan file yang Anda coba impor

mzjn
sumber
3
importlibharus tersedia pada pypi untuk <python2.7
Jeffrey Jose
50
Untuk siapa saja yang datang ke sini dari Google. Perlu dicatat bahwa jika Anda mencoba untuk mengimpor sesuatu dari sub-folder (misalnya, ./feature/email.py) kode akan terlihat sepertiimportlib.import_module("feature.email")
Seanny123
11
Terakhir, ingat juga bahwa Anda tidak dapat mengimpor apa pun jika tidak ada __init__.pydalam folder dengan file yang Anda coba impor.
Seanny123
3
@ mzjn Ini untuk import moduleNametempat moduleName adalah string. Bagaimana dengan from moduleName import *?
Nam G VU
2
Baru saja menemukan jawaban untuk pertanyaan saya di sini jika ada yang membutuhkannya stackoverflow.com/a/31306598/248616
Nam G VU
68

importlib.import_moduleadalah apa yang kamu cari. Ini mengembalikan modul yang diimpor. (Hanya tersedia untuk Python> = 2.7 atau 3.x):

import importlib

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

Setelah itu Anda dapat mengakses apa pun di modul seperti mymodule.myclass, dll.

gecco
sumber
Alternatif imp.load_source(..)menggunakan impmodul seperti yang disarankan dalam jawaban ini stackoverflow.com/questions/67631/…
Evgeni Sergeev
5
@ gecco Ini untuk import moduleNametempat moduleName adalah string. Bagaimana dengan from moduleName import *?
Nam G VU
6

menghabiskan beberapa waktu mencoba mengimpor modul dari daftar, dan ini adalah utas yang membuat saya hampir sampai ke sana - tapi saya tidak memahami penggunaan ___import____ -

jadi inilah cara mengimpor modul dari sebuah string, dan mendapatkan perilaku yang sama seperti hanya mengimpor. Dan coba / kecuali kasus kesalahan juga. :)

  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)

dan ya, untuk python 2.7> Anda memiliki opsi lain - tetapi untuk 2,6 <, ini berfungsi.

tajam
sumber
1

Saya mengembangkan 3 fungsi bermanfaat ini:

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

Dan setiap kali saya ingin memuat ulang instance baru, saya hanya perlu memanggil getInstance () seperti ini:

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

Akhirnya saya bisa memanggil semua fungsi di dalam Mesin Virtual baru:

myInstance.aFunction()

Satu-satunya kekhususan di sini adalah untuk menyesuaikan daftar params (param1, param2, param3) dari instance Anda.

prossblad
sumber
1

Selain menggunakan yang importlibjuga dapat menggunakan execmetode untuk mengimpor modul dari variabel string.

Di sini saya menunjukkan contoh mengimpor combinationsmetode dari itertoolspaket menggunakan execmetode:

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)

Keluaran:

(1, 2)
(1, 3)
(1, 4)
(2, 3)
(2, 4)
(3, 4)
arsho
sumber