Hallo zusammen,
ich würde gerne "registrieren" was ein Modul für Importe durchführen würde. Gibt es da andere Möglichkeiten als regex?
Warum ich das brauche:
Ich habe ein Modul dessen Inhalt ich nicht kenne. Dieses Modul soll importiert werden, das allerdings nur wenn es nichts "verbotenes" importiert. Ich muss also eine Auflistung der durchzuführenden Importe erhalten können, noch bevor das Modul tatsächlich importiert wird.
Erkennen was ein Modul importiert
Hm? Wieso soll das unmöglich sein?
Aus
kann ich doch rauskriegen dass nun "foo" und "foobar" importiert wird??
Aus
Code: Alles auswählen
import foo
from foobar import bar
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Schau Dir mal Abschnitt 30 in der Doku an "Importing Modules". Damit kann man ziemlich viel anstellen... und wie willst Du wirklich semantisch nachvollziehen, ob da eine eigene import-Routine mit implementiert wurde? Ok, dieses Modul muss man wohl auch erst mal mit "import" laden - aber da funzen denn ja doch nur RegExps, um das auszuschließen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
Oh man.. der ModuleFinder.. ich glaubs einfach nicht. Danke!Hyperion hat geschrieben:Schau Dir mal Abschnitt 30 in der Doku an "Importing Modules".
Naja, um genau zu sein habe ich keine "verbotenen" Module, nur welche die "erlaubt" sind, includes also. Wenn da was dabei ist was nicht bekannt ist, wirds halt einfach nicht importiert (also das ganze Modul) und gut ist.Hyperion hat geschrieben:und wie willst Du wirklich semantisch nachvollziehen, ob da eine eigene import-Routine mit implementiert wurde?
Nunja, falls tatsächlich es jemand schafft sys.path bzw. sys.meta_path zu verändern bevor das Modul importiert wird, ist doch sowieso schon alles zu spät, oder etwa nicht? Und falls das ganze innerhalb des Moduls geschieht, muss dennoch "sys" importiert werden, was definitiv zu den nicht erlaubten gehören wird. Falls dann noch jemand "__import__" nutzt wirds halt auch verhindert. Das ist ja ganz leicht mit einer Suche nach eben diesem Namen gelöst.DasIch hat geschrieben:Was wenn jemand vorher PYTHONPATH setzt, sys.path verändert oder sys.meta_path nutzt? Was wenn jemand zum importieren __import__ nutzt?
Inwieweit allerdings eine Umgebungsvariable wie PYTHONPATH nun eine Rolle spielt sehe ich gerade nicht.
Man könnte das Skript ja auch als Benutzer mit stark eingeschränkten Rechten ausführen. Dann sollte sich die Befürchtung, dass Schindluder via `sys` getrieben wird (z.B. Löschen von Dateien), einigermaßen erübrigt haben. Was ist denn der eigentliche Grund, warum du Module verbieten willst?
//edit: Ok, Löschen von Dateien ist in Bezug auf `sys` kein gutes Beispiel gewesen. Aber ich vermute, um solche Dinge geht's im Prinzip, oder?
//edit: Ok, Löschen von Dateien ist in Bezug auf `sys` kein gutes Beispiel gewesen. Aber ich vermute, um solche Dinge geht's im Prinzip, oder?
Du kannst den Namen auch zur Laufzeit zusammensetzen.Gremlin hat geschrieben:Falls dann noch jemand "__import__" nutzt wirds halt auch verhindert. Das ist ja ganz leicht mit einer Suche nach eben diesem Namen gelöst.
Code: Alles auswählen
im = eval(''.join(['_', '_', 'i', 'm', 'p', 'o', 'r', 't', '_', '_']))
@snafu
Nunja, es geht letztlich um das Thema ein Modul dynamisch zu laden. Also als Basis habe ich einen String, der repräsentiert Python Code und wird mittels "Exec string in dict" in ein Modul umgewandelt. In einem eigenen Prozess kann ich das schlecht ausführen, denn zum einen erhalte ich den String nicht von einem Dateiobjekt (müsst ich also auch erst erstellen) und zum anderen benötigt der Code innerhalb dieses Strings Zugriff auf aktuelle Daten der Laufzeit.
Da der eigentliche Prozess mit Admin-Rechten läuft ist das natürlich eine heikle Sache, dazu kommt noch dass der erwähnte String aus dem Netzwerk kommt, also wird die Sache noch heikler. Selbstverständlich läuft die Übertragung übers Netzwerk verschlüsselt ab, aber als weitere Vorsichtsmaßnahme dachte ich mir, ich schließe einfach aus dass bestimmte Dinge mit dem was da "blind" importiert wird gemacht werden können. Zuerst dachte ich da an eine eigene kleine Mini-Sprache die mittels pyparsing oder ähnlichem realisiert wird, aber nachdem das über einfache Anweisungen hinaus geht (Variablen, Typen, Bedingungen) wars mir doch etwas zu viel Aufwand.
Genau genommen gehts eigentlich nur, was mir jetzt so spontan einfällt, um die Blockade von socket, urllib(2) und ähnlichen Importen. Denn lesen und schreiben von Daten ist essentiell.
Nunja, es geht letztlich um das Thema ein Modul dynamisch zu laden. Also als Basis habe ich einen String, der repräsentiert Python Code und wird mittels "Exec string in dict" in ein Modul umgewandelt. In einem eigenen Prozess kann ich das schlecht ausführen, denn zum einen erhalte ich den String nicht von einem Dateiobjekt (müsst ich also auch erst erstellen) und zum anderen benötigt der Code innerhalb dieses Strings Zugriff auf aktuelle Daten der Laufzeit.
Da der eigentliche Prozess mit Admin-Rechten läuft ist das natürlich eine heikle Sache, dazu kommt noch dass der erwähnte String aus dem Netzwerk kommt, also wird die Sache noch heikler. Selbstverständlich läuft die Übertragung übers Netzwerk verschlüsselt ab, aber als weitere Vorsichtsmaßnahme dachte ich mir, ich schließe einfach aus dass bestimmte Dinge mit dem was da "blind" importiert wird gemacht werden können. Zuerst dachte ich da an eine eigene kleine Mini-Sprache die mittels pyparsing oder ähnlichem realisiert wird, aber nachdem das über einfache Anweisungen hinaus geht (Variablen, Typen, Bedingungen) wars mir doch etwas zu viel Aufwand.
Genau genommen gehts eigentlich nur, was mir jetzt so spontan einfällt, um die Blockade von socket, urllib(2) und ähnlichen Importen. Denn lesen und schreiben von Daten ist essentiell.
Gut, das Argument ist... vernichtend.DasIch hat geschrieben:Du kannst den Namen auch zur Laufzeit zusammensetzen.
@Gremlin: Für Sockets brauchst Du nichts importieren wenn Dein Code das schon irgendwo vorher gemacht hat:
Code: Alles auswählen
python -c "import socket; print [o for o in object.__subclasses__() if 'socket' in o.__name__]"
[<class 'socket._closedsocket'>, <type '_socket.socket'>, <class 'socket._socketobject'>]