2017-11-17 4 views
2

Wir erstellen eine Bibliothek, und ein Teil davon ist ein Modul, das verschiedene Datenbankschnittstellen auf verschiedenen Systemen bereitstellt.Nicht verwendete Importe in Python3 ignorieren

class DbInterface1(object): 
    """Uses MySQLdb, and is useful on system A.""" 
    def __init__(): 
     pass 

class DbInterface2(object): 
    """Uses SQLAlchemy, and is useful on system B.""" 
    def __init__(): 
     pass 

Wir möchten Importe überspringen, die nicht verwendet werden. Auf einem System mit der Nummer MySQLdb verwenden wir zum Beispiel DbInterface1 und sollten SQLAlchemy nicht installieren. Das heißt, auf System A, wir es so verwenden würde:

from ourlibrary.dbinterfaces import DbInterface1 

... 

Offensichtlich ist dies nicht funktionieren:

import MySQLdb 
import sqlalchemy 

class DbInterface1(object): 
    """Uses MySQLdb, and is useful on system A.""" 
    def __init__(): 
     pass 

class DbInterface2(object): 
    """Uses SQLAlchemy, and is useful on system B.""" 
    def __init__(): 
     pass 

Wir gingen davon aus, dass die Einfuhren in die Klassen zu bewegen, die sie verwenden funktionieren würde, da der Bibliotheks-Client nicht etwas importiert, das er nicht verwendet, aber immer noch fehlgeschlagene Abhängigkeiten sind.

class DbInterface1(object): 
    """Uses MySQLdb, and is useful on system A.""" 
    import MySQLdb 

    def __init__(): 
     pass 

class DbInterface2(object): 
    """Uses SQLAlchemy, and is useful on system B.""" 
    import sqlalchemy 

    def __init__(): 
     pass 

Was ist der richtige Weg, dies zu tun? Ist es überhaupt möglich?

+3

Versuchen Sie, den 'import' in den' _init__() 'zu verschieben, so dass der Import erst dann erfolgt, wenn eine Instanz der Klasse erstellt wurde. Wenn das nicht genug ist, dann sind hier mehr Werkzeuge: https://docs.python.org/3/library/modules.html – gammazero

+0

@gammasero Das funktioniert, wenn wir die Importe für jede Funktion hinzufügen, die sie verwendet (im Idealfall könnten wir machen das ist nur "__init __()", aber es ist jetzt nicht richtig). Wir konnten 'importlib.util.find_spec()' verwenden, um vor dem Import nach der Existenz des Moduls zu suchen, was jedoch zu einem unerwarteten Ergebnis führt, wenn ein Modul in einem System fehlt, auf dem es installiert werden sollte (dh wenn system A fehlt 'MySQLdb' aus irgendeinem Grund. Du hast uns also zwei Arbeitsoptionen gegeben: -D, aber beides ist nicht ideal. – Kittsil

Antwort

1

Warum verpacken Sie Ihre Importe nicht in einen try-except-Block?

try: 
    import MySQLdb 
except ImportError: 
    pass 
try: 
    import sqlalchemy 
except ImportError: 
    pass 

Dies sollte ermöglichen, Ihr Skript auszuführen, auch wenn kein Modul installiert ist.

Sie können die obige Methode ändern, um nachzuverfolgen, ob die importierten Module vorhanden sind, um zu überprüfen, ob eine Klasse auf einem bestimmten System verwendet werden kann.

try: 
    import MySQLdb 
except ImportError: 
    module_MySQLdb = False 
else: 
    module_MySQLdb = True 

Dann könnten Sie diese Informationen in einer Klassenvariablen speichern und überprüfen, bevor die Klasse instanziieren.

class DbInterface1(object): 
    """Uses MySQLdb, and is useful on system A.""" 
    is_avaliable = module_MySQLdb 
    def __init__(self): 
     pass 

if DbInterface1.is_avaliable: 
    dbm = DbInterface1() 

Oder Sie könnten ein Wörterbuch verwenden (zB avaliable_modules = {'MySQLdb':module_MySQLdb}) und importieren Sie es mit Ihrer Klasse zusammen.

+0

Wenn 'find_spec()' 'verwendet wird, werden die Fehler ausgeblendet, wenn das Modul nicht auf einem System installiert ist, auf dem es erwartet wird und daher nicht ideal ist. – Kittsil

+0

Ja, aber Sie könnten eine Variable verwenden, um die Informationen zu speichern (ein bisschen "Hacky", ich weiß). Ich habe meinen Beitrag aktualisiert, um ein Beispiel zu geben. –

Verwandte Themen