Seite 1 von 1

Module aus dem Internet importieren

Verfasst: Freitag 8. Juni 2007, 10:16
von Spontifixus
Moin zusammen,

Die Situation ist die Folgende. Ich erstelle im Rahmen meiner Diplomarbeit eine Datenbank, auf die über zwei verschiedene Wege zugegriffen werden soll. Weg Nummer Eins: Ein Webinterface, Weg Nummer Zwei eine auf dem Rechner des Benutzers laufende lokale Python-Anwendung.
Zur Verarbeitung der Daten möchte ich bestimmte Klassen definieren, die anschließend von den jeweiligen Anwendungen (Webinterface und lokale Anwendung) instanziiert werden sollen (Stichwort MVC).

Problem dabei: Ist es möglich aus der lokalen Anwendung heraus ein Pythonmodul zu laden, dass auf einem Webserver liegt?

Eine Idee wäre es, das Modul herunterzuladen und es dann zu importieren, allerdings hat der Benutzer nicht gezwungenermaßen Schreibrechte auf das Verzeichnis wo die Anwendung später liegt.

Gibt es noch andere Möglichkeiten um ein Modul aus dem Internet zu laden?

Viele Grüße,
Markus :)

Verfasst: Freitag 8. Juni 2007, 10:52
von Y0Gi
Meines Wissens geht das nicht, und das ist auch gut so *an Code-Injection bei PHP denk*. Du könntest natürlich den Server den Quelltext des Moduls als Plaintext ausliefern lassen, den vom lokalen Client in eine Datei speichern und dann laden lassen - da rate ich aber energisch von ab.

Solltest du nicht besser einen Webservice verwenden?

Re: Module aus dem Internet importieren

Verfasst: Freitag 8. Juni 2007, 10:57
von gerold
Spontifixus hat geschrieben:Ich erstelle im Rahmen meiner Diplomarbeit eine Datenbank, auf die über zwei verschiedene Wege zugegriffen werden soll. Weg Nummer Eins: Ein Webinterface, Weg Nummer Zwei eine auf dem Rechner des Benutzers laufende lokale Python-Anwendung.
[...]
Zur Verarbeitung der Daten möchte ich bestimmte Klassen definieren, die anschließend von den jeweiligen Anwendungen (Webinterface und lokale Anwendung) instanziiert werden sollen (Stichwort MVC).
Hallo Markus!

Code: Alles auswählen

            Datenbank
                |
            Middleware
                |
       -------------------
      |                   |
 Webinterface   Lokales Python-Programm
Was will ich damit sagen? Mach einzelne Programme daraus und nicht ein ganzes Programm.
Die Datenbank kümmert sich um die Datenhaltung.
Die Middleware greift direkt auf die Datenbank zu und kümmert sich darum, dass die Clients eine vereinfachte Schnittstelle zur Datenbank haben.
Die Clients richten ihre Anfragen an die Middleware, die die Daten aus der Db holt und weiter gibt.
Einfachste Kommunikation zwischen den Clients und der Middleware --> XMLRPC, das in Python sehr gut implementiert wurde.

Für das Webinterface eignet sich jedes Web-Framework oder sogar CGI. Ich schlage dir CherryPy vor. Und für das GUI-Programm wxPython.

EDIT:

Eine Middleware hat allerdings auch seine Nachteile. Eine Middleware kann ziemlich schnell aus allen Nähten platzen. Mir persönlich ist schon passiert, dass die Middleware so umfangreich wurde, dass es inzwischen einfacher ist, direkt auf die Datenbank zuzugreifen, als für jede Kleinigkeit über die Middleware zu gehen. Man muss sich als Programmierer stark zurück halten, um doch über die Middleware zu gehen. Außerdem hat jedes gute Datenbanksystem eine Benutzer- und Rechteverwaltung eingebaut. Wenn du über eine Middleware gehst, dann musst du dich selber darum kümmern. Auch um die Lastverteilung. Connectionpooling usw.

Als Alternative kann man die Funktionen der Middleware direkt in die Datenbank verlegen. Das hat fast nur Vorteile. Eine gute Datenbank, wie z.B. PostgreSQL kann sogar direkt mit Python programmiert werden. Die Rechte können granular auf einzelne Objekte verteilt werden. Usw.

mfg
Gerold
:-)

PS: http://www.postgresql.org/docs/8.2/static/plpython.html

Re: Module aus dem Internet importieren

Verfasst: Freitag 8. Juni 2007, 12:04
von Spontifixus
Moin!

Vielen Dank für die Antworten!
gerold hat geschrieben:

Code: Alles auswählen

            Datenbank
                |
            Middleware
                |
       -------------------
      |                   |
 Webinterface   Lokales Python-Programm
Was will ich damit sagen? Mach einzelne Programme daraus und nicht ein ganzes Programm.
Die Datenbank kümmert sich um die Datenhaltung.
Die Middleware greift direkt auf die Datenbank zu und kümmert sich darum, dass die Clients eine vereinfachte Schnittstelle zur Datenbank haben.
Die Clients richten ihre Anfragen an die Middleware, die die Daten aus der Db holt und weiter gibt.
Genau das meinte ich mit MVC (Model View Control) - nur auf XMLRPC war ich bislang nicht gekommen.

Mir ist allerdings inzwischen aufgefallen, dass ein solcher Klimmzug wohl gar nicht nötig sein wird. Die Lokale Anwendung wird per SVN verteilt, da kann ich die entsprechenden Module auch gleich mit ausliefern...

Gruß,
Markus :)

Verfasst: Freitag 8. Juni 2007, 21:17
von birkenfeld
Prinzipiell kann man natürlich schon einen Import-Hook schreiben, der Module bei Bedarf aus dem lädt und importiert... (löst zwar das OP-Problem nicht, ist aber ein schönes Beispiel für Import-Hooks)

Das ganze würde dann so ungefähr funktionieren:

Code: Alles auswählen

import sys, new, urllib, posixpath

class UrlHook:
    def __init__(self, path):
        if not path.startswith('http://'):
            # der Hook ist nicht zustaendig
            raise ImportError
        self.path = path

    def find_module(self, fullname):
        if "." in fullname:
            # Vorerst keine Packages...
            return None
        return self

    def load_module(self, fullname):
        url = posixpath.join(self.path, fullname+'.py')
        f = urllib.urlopen(url)
        try:
            code = f.read()
            # Neues Modulobjekt erstellen und den Code
            # darin ausfuehren
            mod = new.module(fullname)
            sys.modules.setdefault(fullname, mod)
            mod.__file__ = url
            mod.__loader__ = self
            exec code in mod.__dict__
            return mod
        finally:
            f.close()


# den Hook fuer jeden Eintrag in sys.path aufrufen
sys.path_hooks.append(UrlHook)
# Beispielpfad
sys.path.append('http://pydoc.gbrandl.de/')
# Modul von dieser URL importieren
import webmod
Vorsicht: wer mir nicht traut, sollte den Code nicht bei sich ausführen, oder zumindest vorher http://pydoc.gbrandl.de/webmod.py herunterladen und sich vergewissern, dass nichts schädliches darinsteht ;)

Verfasst: Samstag 9. Juni 2007, 05:37
von Whitie
Hallo Spontifixius,
Du könntest die Kommunikation auch über Pyro (Python Remote Objects) abwickeln. Da gibt es eine Option (mobile code), die aktiviert werden kann und bei Bedarf benötigte Module zum Client überträgt.
Ich hab leider keine Beispiele zur Hand, war aber damals recht einfach als ich es benutzt habe.

Gruß, Whitie

Verfasst: Samstag 9. Juni 2007, 08:02
von gerold
birkenfeld hat geschrieben:Prinzipiell kann man natürlich schon einen Import-Hook schreiben, der Module bei Bedarf aus dem lädt und importiert... (löst zwar das OP-Problem nicht, ist aber ein schönes Beispiel für Import-Hooks)
Hallo birkenfeld!

Damit hast du mich völlig überrascht. :D Ich hatte noch nie vorher etwas von "path_hooks" gehört. Wieder etwas, was die Erweiterbarkeit von Python demonstriert.

lg
Gerold
:-)

Verfasst: Samstag 9. Juni 2007, 10:30
von birkenfeld
gerold hat geschrieben: Damit hast du mich völlig überrascht. :D Ich hatte noch nie vorher etwas von "path_hooks" gehört.
Evtl. hast du sie aber schon benutzt; der zipimporter ist nämlich genau so ein Hook :)

Verfasst: Samstag 9. Juni 2007, 12:52
von Leonidas
Der ganze UrlHook erinnert von der Funktionalität etwas an den aus PLT Scheme bekannten PLaneT. Dort ist es auch Möglich zur Laufzeit Module runterzuladen und zu importieren. Allerdings werden dort die Module dann abgespeichert, aber das ist bei birkenfelds Code auch sehr einfach nachzurüsten.

Verfasst: Montag 11. Juni 2007, 10:18
von Spontifixus
Moin,

nochmals vielen Dank für die vielen Antworten.

Ich habe mich für die erstgenannte Methode (XML-RPC) entschieden. Ich hatte schon einen Teil des Control-Layers in PHP umgesetzt, so dass ich mir die erneute Implementierung desselben in Python sparen kann.

Folgende Komponenten verwende ich:

Auf seiten PHP (der XML-RPC-Server) verwende ich PHPXMLRPC, auf Seiten Python kommt die xmlrpclib zum Einsatz.

Viele Grüße,
Markus :)