Wählen Sie den Adapter abhängig von den installierten Libraries dynamisch aus

8

Ich entwerfe eine Bibliothek, die über Adapter verfügt, die eine Vielzahl von Bibliotheken unterstützen. Ich möchte, dass die Bibliothek dynamisch auswählt, welcher Adapter, auf dem die Bibliothek installiert ist, beim Importieren bestimmter Klassen auf der Maschine installiert ist.

Ziel ist es, die Bibliothek, von der das Programm abhängt, ändern zu können, ohne Änderungen am Code vornehmen zu müssen. Diese spezielle Funktion ist für den Umgang mit RabbitMQ-Verbindungen gedacht, da wir viele Probleme mit pika hatten, zu denen wir wechseln möchten eine andere Bibliothek, z pyAMPQ oder rabbitpy ohne den zugrunde liegenden Code zu ändern.

Ich dachte daran, etwas in der Datei __init__.py von servicelibrary.simple zu implementieren.

%Vor%

Wenn der Benutzer die Bibliothek importiert

%Vor%

Die darunterliegende Ebene sieht ungefähr so ​​aus

alternative.py

%Vor%

synchron.py

%Vor%

Dies würde automatisch das zweite auswählen, wenn das erste nicht installiert ist.

Gibt es eine bessere Möglichkeit, so etwas zu implementieren? Wenn jemand eine Bibliothek / einen Adapter mit einer ähnlichen Implementierung verknüpfen könnte, die ebenfalls hilfreich wäre.

[Bearbeiten]

Was wäre der sauberste Weg, um so etwas zu implementieren? In der Zukunft möchte ich auch die Standardpräferenz ändern können. Letztendlich kann ich mich mit der installierten Bibliothek begnügen, da ich das kontrollieren kann, aber es wäre ein nettes Feature.

Alexanders Vorschlag ist interessant, aber ich würde gerne wissen, ob es einen saubereren Weg gibt.

[Bearbeiten2]

Das ursprüngliche Beispiel wurde vereinfacht. Jedes Modul kann mehrere Arten von Importen enthalten, z. Consumer und Publisher.

    
eandersson 23.10.2013, 11:32
quelle

5 Antworten

3

Das importlib.import_module könnte tun, was Sie brauchen:

%Vor%

Ich denke, das ist nicht die fortschrittlichste Technik, aber die Idee sollte klar sein. Und Sie können sich auch das Modul imp ansehen.

    
Alexander Zhukov 23.10.2013, 11:49
quelle
3

Eine flexible Lösung mit importlib . Dies ist eine vollständige, funktionierende Lösung, die ich getestet habe.

Zuerst der Header:

%Vor%

Wir importieren das benötigte Modul, setzen unser Kennzeichen und spezifizieren unsere Module. modules ist ein Wörterbuch mit dem Schlüssel als Standardmodul und dem Wert als Liste von Alternativen.

Als nächstes der Import-Ant-Teil:

%Vor%

Und um die Klassen zu haben, tun Sie einfach:

%Vor%

Mit dieser Lösung können Sie mehrere Alternativen gleichzeitig haben. Zum Beispiel können Sie sowohl rabbitpy als auch pyAMPQ als Alternativen verwenden.

Hinweis: Funktioniert sowohl mit Python 2 als auch mit Python 3.

Wenn Sie weitere Fragen haben, zögern Sie nicht, zu kommentieren und zu fragen!

    
aIKid 01.11.2013 16:43
quelle
1

Sie haben die richtige Idee. Ihr Fall funktioniert, weil jedes Unterobjekt dieselbe Art von Klassen aufweist, z. Beide APIs haben eine Klasse namens Publisher und Sie können einfach sicherstellen, dass die richtige Version importiert wird.

Wenn das nicht stimmt (wenn die möglichen Implementierungen A und B nicht ähnlich sind), schreiben Sie Ihre eigene Fassade, die nur Ihre eigene einfache API ist, die dann die echte API mit den richtigen Methoden / Parametern für diese Bibliothek aufruft / p>

Offensichtlich erfordert das Wechseln zwischen den Optionen einen gewissen Overhead (ich kenne Ihren Fall nicht, aber sagen wir einmal, Sie hätten zwei Bibliotheken, um eine geöffnete Datei zu durchsuchen, und die Bibliothek kümmert sich um das Öffnen der Datei Wechseln Sie in die zweite Bibliothek in der Mitte der Datei und erwarten Sie, dass sie dort beginnt, wo die erste Bibliothek gestoppt wurde. Aber es ist nur eine Frage des Speicherns:

%Vor%

usw.

    
Corley Brigman 29.10.2013 19:01
quelle
1

Ich kenne zwei Methoden, eine ist wild verwendet und eine andere ist mein Rätselraten. Sie können einen für Ihre Situation wählen.

Der erste, der häufig verwendet wird, z. B. from tornado.concurrent import Future .

%Vor%

Dann können Sie from tornado.concurrent import Future in anderen Dateien verwenden.

Der zweite, der meine Vermutung ist, und ich schreibe einfache Demo, aber ich habe es nicht in der Produktionsumgebung verwendet, weil ich es nicht brauche.

%Vor%

Sie können das Skript vor dem anderen Skript import servicelibrary.simple.synchronous ausführen. Dann können Sie das Skript wie zuvor verwenden:

%Vor%

Das einzige, was ich mich frage, ist, was sind die consequences meiner Ratespiele.

    
Goat 01.11.2013 14:25
quelle
1

Basierend auf den Antworten bin ich mit der folgenden Implementierung für Python 2.7 gelandet.

Beispiele sind für stackoverflow vereinfacht. .

%Vor%

Obwohl ich auch einige meiner Projekte mit Python 2.6 betreiben musste, musste ich entweder den Code modifizieren oder importlib . Das Problem mit einer Produktionsplattform ist, dass es nicht immer einfach ist, neue Abhängigkeiten einzubauen.

Dies ist der Kompromiss, den ich mir ausgedacht habe, basierend auf __import__ anstatt importlib .

Es könnte sich lohnen, zu überprüfen, ob sys.modules tatsächlich den Namespace enthält, so dass kein KeyError ausgelöst wird, aber es ist unwahrscheinlich.

%Vor%     
eandersson 18.11.2013 09:49
quelle