dize değişkeninden modülü içe aktar


183

Ben ilgilenen alt modül paketleri tarafından sağlanan MPL kendi sağlanan farklı iç içe matplotlib (MPL) kitaplığı için bir belge (kişisel) üzerinde çalışıyorum. Gelecekteki MPL sürümlerinden belge oluşturmayı otomatikleştireceğini umduğum Python betiği yazıyorum.
İlgilenilen alt modülleri / paketleri seçtim ve hangi sınıfları oluşturacağımı ve bunları işleyeceğim ana sınıflarını listelemek istiyorumpydoc

Sorun Python dize alt modül yüklemek için talimat için bir yol bulamıyor olmasıdır. İşte ne denedim bir örnek:

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

.

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

.

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

Ve yukarıdaki listelerin pprint ile 3 şekilde karşılaştırılması:

resim açıklamasını buraya girin

Neye yüklendiğini anlamıyorum y- temel matplotlibartı başka bir şey, ama istediğim bilgi eksik ve bu matplotlib.textpaketten ana sınıflar . Ekran görüntüsünde en üst mavi renkli kısım ( xliste)

Lütfen Sfenks'i farklı bir yaklaşım olarak önermeyin.


__import__(str)Standart importstatemetn yerine neden kullanmanız gerektiğini açıklayabilir misiniz ?
thesamet

Çünkü hangi öğelerin MPL alt modülleri olduğunu listeleyeceğim ve yöntem yollarını alacağım
theta

9
@thesamet - hadi - bu işlevselliği isteyebileceğiniz sonsuz fikirler var. Metin kitaplık yapılandırmanız olduğunda, bunları isimle yükleyebilirsiniz, bu da importifadeyle pek işe yaramaz . İşte bir kullanım örneği: djangosnippets.org/snippets/3048
Tomasz Gandor

Yanıtlar:


279

__import__Fonksiyon anlamak için biraz zor olabilir.

Eğer değiştirirsen

i = __import__('matplotlib.text')

için

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

o izaman atıfta bulunacaktır matplotlib.text.

Python 2.7 ve Python 3.1 veya üzeri sürümlerde şunları kullanabilirsiniz importlib:

import importlib

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

Bazı notlar

  • Bir alt klasörden bir şey içe aktarmaya çalışıyorsanız ./feature/email.py, kod şöyle görünecektirimportlib.import_module("feature.email")

  • İçe aktarmaya __init__.pyçalıştığınız dosyanın bulunduğu klasörde hiçbir şey içe aktarılamaz


3
importlibpypi için <python2.7
Jeffrey Jose

50
Buraya Google'dan gelen herkes için. Bir alt klasörden (örneğin ./feature/email.py) bir şey içe importlib.import_module("feature.email")
aktarmaya çalışıyorsanız

11
Son olarak, içe aktarmaya __init__.pyçalıştığınız dosyada klasörde hiçbir şey yoksa hiçbir şeyi içe aktaramayacağınızı da unutmayın .
Seanny123

3
@mzjn Bu, import moduleNamemoduleName öğesinin dize olduğu yerdir. Nasıl from moduleName import *?
Nam G VU

2
Herhangi birinin ihtiyacı olması halinde sorumun cevabını burada buldum stackoverflow.com/a/31306598/248616
Nam G VU

68

importlib.import_modulearadığınız şey bu. İçe aktarılan modülü döndürür. (Yalnızca Python> = 2.7 veya 3.x için kullanılabilir):

import importlib

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

Daha sonra modüldeki herhangi bir şeye mymodule.myclassvb. Erişebilirsiniz .



5
@gecco Bu, import moduleNamemoduleName öğesinin dize olduğu yerdir. Nasıl from moduleName import *?
Nam G VU

6

bir listeden modülleri almaya çalışırken biraz zaman harcadı ve bu beni orada en çok yol iş parçacığı - ama ___import____ kullanımını kavramadım -

bir dizeden bir modülü nasıl içe aktaracağınız ve sadece içe aktarma ile aynı davranışı nasıl elde edeceğiniz aşağıda açıklanmıştır. Hata durumunu da deneyin / hariç tutun. :)

  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)

ve evet, python 2.7> için başka seçenekleriniz var - ancak 2.6 <için bu işe yarıyor.


1

Bu 3 yararlı işlevi geliştirdim:

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

Ve her zaman yeni bir örneği yeniden yüklemek istiyorum ben sadece getInstance () şöyle çağırmak zorunda:

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

Son olarak, yeni Eşgörünüm içindeki tüm işlevleri çağırabilirim:

myInstance.aFunction()

Buradaki tek özgüllük, örneğinizin params listesini (param1, param2, param3) özelleştirmektir.


1

Bunun dışında, bir modül bir dize değişkeninden içe aktarma yöntemi importlibde kullanılabilir exec.

Burada combinationsyöntemi itertoolskullanarak paketten yöntemi alma örneği gösteriyor exec:

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)

Çıktı:

(1, 2)
(1, 3)
(1, 4)
(2, 3)
(2, 4)
(3, 4)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.