string to command

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
murph
User
Beiträge: 622
Registriert: Freitag 14. April 2006, 19:23
Kontaktdaten:

hi!
wie kann man einen string zu einem python-command amchen?
mir schwebt vor, usersettings in einer datei anzulegen,
die jeder auslesen können soll und auch modifizieren, falls eine fehldiagnose vorliegt.
nun habe ich das problem, dass ich nicht immer fragen will

Code: Alles auswählen

if "string" = string:
    command = string
gibt es dafür eine lösung?
helmut
User
Beiträge: 57
Registriert: Mittwoch 2. November 2005, 07:45
Wohnort: Dormagen

Hallo, schau hier mal.
Gruss, Helmut
Joghurt
User
Beiträge: 877
Registriert: Dienstag 15. Februar 2005, 15:07

murph hat geschrieben:wie kann man einen string zu einem python-command amchen?
Mit eval. Denk aber daran, dass ein böser Bub auch sowas wie "import os;os.unlink('Wichtige Datei')" übergeben kann.
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

ich würde nicht eval benutzen.

hasattr() und getattr() erscheinen mir in 99 % der Fälle als sinnvoller.
Joghurt
User
Beiträge: 877
Registriert: Dienstag 15. Februar 2005, 15:07

Mad-Marty hat geschrieben:hasattr() und getattr() erscheinen mir in 99 % der Fälle als sinnvoller.
Er "will einen String zu einem Pythoncommand machen"
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

Joghurt hat geschrieben:
Mad-Marty hat geschrieben:hasattr() und getattr() erscheinen mir in 99 % der Fälle als sinnvoller.
Er "will einen String zu einem Pythoncommand machen"
Das stimmt. Aber gerade bei konfigurationsdateien, wo man wahrscheinlich den optionswert auf ein objekt übertragen wird könnte man die *attr nutzen.

Zumindest lese ich das aus den ersten paar zeilen.

Ist ja auch egal, aber eval(cfg) ist so ziemlich das grösste sicherheitsloch was es gibt ;-)

Und manche sachen gehen dann auch nur mit exec.
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Mad-Marty hat geschrieben:Das stimmt. Aber gerade bei konfigurationsdateien, wo man wahrscheinlich den optionswert auf ein objekt übertragen wird könnte man die *attr nutzen.
s
Zumindest lese ich das aus den ersten paar zeilen.

Ist ja auch egal, aber eval(cfg) ist so ziemlich das grösste sicherheitsloch was es gibt ;-)
Kommt drauf an, wann man eval benutzt. Wenn ein User in seine Konfigurationsdatei Befehle eintraegt, die dann, wenn er das zugehoerige Programm als eben dieser User startet, mit eval ausgewertet werden -- wo ist das Problem? Er kann dann mittels Konfigurationsdatei das machen, was er auch in einer Shell oder einem Dateimanager anrichten kann.

Hindert mich ja auch keiner dran, in meiner .bashrc rm -r wichtiger_ordner einzutragen, oder in meiner .emacs (delete-direcory wichtiger_ordner), oder in meiner .fvwm2rc Exec exec rm -r wichtiger_ordner...

Problematisch wird's erst, wenn ein Programm mit priviligierten Rechten Eingaben von normalen Usern/Userprogrammen oder von der "Aussenwelt" entgegennimmt, die dann mit eval ausgewertet werden.... Oder wenn schlimme Befehle ausgewertet werden an Stellen, wo eigentlich nur eingeschraenkte, harmlose Eingaben gemacht werden und der User nicht mir rechnet.
murph
User
Beiträge: 622
Registriert: Freitag 14. April 2006, 19:23
Kontaktdaten:

inwiefern seht ihr eval denn als sicherheitslücke?
und wie funktioniert '*args'?
Das steht in meinem Pythonbuch nicht drin.
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Stell dir mal vor, Lisa und Sebastian spielen ein Spiel uebers Netz. Ihre beiden Programme muessen miteinander kommunizieren, z.B. werden Strings ueber Sockets ausgetauscht. Nun ist Lisas Programm ganz boese und schickt einen gemeinen String an Sebastians Program ("import os;os.unlink('Wichtige Datei')"), um mal Joghurts Beispiel aufzugreifen.

Wenn jetzt Sebastians Programm ein eval drauf anwendet, weil es weniger boese Sachen erwartet, wird diese wichtige Datei auf Sebastians Computer geloescht, was der wahrscheinlich nicht will. Und das wichtige: Lisa selbst oder Lisas Programm haetten das gar nicht gedurft, weil sie nicht Rechte auf Sebastians Rechner haben, um Sebastians wichtige Datei zu loeschen, aber Lisas Programm hat quasi Sebastians eigenes Programm mit dessen eigenen Rechten missbraucht.

Aber wie ich schon sagte, kommt halt auf den Zusammenhang an.
murph
User
Beiträge: 622
Registriert: Freitag 14. April 2006, 19:23
Kontaktdaten:

ich bin grade dabei, was für sqlite zu machen.
ich weiß, dass es da schon was gibt, wollte mich aber mal in den klassen austoben und dachte mir, dass man da mal was schreiben könnte.
aber ich will dem nutzer kein modul vorschreiben, deshalb soll geprüft werden, was für ein sqlite-modul installiert ist um das dann zu importieren.
weil ich aber nicht immer wieder alles testen will, soll das in eine textdatei.
+nun habe ich das problem, dass bei import keine variablen akzeptiert werden.
die *args habe ich im forum gefunden...
murph
User
Beiträge: 622
Registriert: Freitag 14. April 2006, 19:23
Kontaktdaten:

ich habe nun damit ein problem.
exec funktioniert nur eingeschränkt...hier der code(ausschnitssweise):

Code: Alles auswählen

def Importer():
    getter = UserSettings()
    module = getter.get_module()
    exec("import %s as sqlite_module") % module
[....]
class main:
    def greeting(self):
        self.conn_var = raw_input("Please enter the Path to the SQLite-Database: \n")
        Importer()
        self.conn = sqlite_module.connect(self.conn_var)
        self.cur = self.conn.cursor
    def cmdgetter():
        cmd = raw_input("§§§")
        self.cur.execute(cmd)
        self.cur.commit()      
        try:
            TELL(self.cur.fetchall())
        except:
            TELL("Things were commited!")
        main().cmdgetter()
nun meint der aber, das 'sqlite_module' nicht belegt wäre, obwohl ich mit exec dieses getan habe. was tun?
murph
User
Beiträge: 622
Registriert: Freitag 14. April 2006, 19:23
Kontaktdaten:

ich werde konkreter:

Code: Alles auswählen

#!/usr/bin/env python
exec("import sqlite as sqlite_module")
conn = sqlite_module.connect("test.db")
cur = conn.cursor()
cur.execute("SELECT * from t1")
print cur.fetchall()
Das Funktioniert!!!!!
aber das oben geschickte beispiel nicht, er denkt, das sqlite_module sei ein attribut, soll aber die importierte datenbank ansprechen (import sth as sth)
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

murph hat geschrieben:ich werde konkreter:

Code: Alles auswählen

#!/usr/bin/env python
exec("import sqlite as sqlite_module")
Hi murph!

Das importieren von vorher nicht bekannten Modulen funktioniert mit __import__(): http://docs.python.org/lib/built-in-funcs.html#l2h-6

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

murph hat geschrieben:mir schwebt vor, usersettings in einer datei anzulegen,
die jeder auslesen können soll und auch modifizieren,
Hi murph!

Das ist eine gute Idee. Dafür gibt es auch schon ein Modul, das ideal dafür geeignet ist, Einstellungen auszulagern -- den ConfigParser: http://docs.python.org/lib/module-ConfigParser.html

Andere Formate empfehle ich erst dann, wenn es wichtig ist, auch verschachtelte Einstellungen in eine Config-Datei zu schreiben.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Joghurt hat geschrieben:Mit eval. Denk aber daran, dass ein böser Bub auch sowas wie "import os;os.unlink('Wichtige Datei')" übergeben kann.
Hi Joghurt!

eval ist eher abgespeckt. Man kann damit einen Python-Ausdruck (1+1 oder 'hallo'*2) ausführen lassen, aber kein Programm. Es lassen sich nicht alle Kommandos ausführen. Ein Import ist nicht möglich. Allerdings kann man meistens davon ausgehen, dass zumindest os, os.path und sys bereits importiert sind. Dann sind solche Konstrukte wie "os.remove(sys.executable)" sehrwohl möglich. Bitte nicht ausprobieren. :lol:

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
murph
User
Beiträge: 622
Registriert: Freitag 14. April 2006, 19:23
Kontaktdaten:

aber wie übergebe ich dem __import__ ein 'as'?
ich will ja später nur noch eine variable nutzen, damit man diesen code mit allen sqlite-wrappern nutzen kann, die die standardfunktionen haben.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

murph hat geschrieben:aber wie übergebe ich dem __import__ ein 'as'?
Hi murph!

Code: Alles auswählen

ver = __import__("sys").version
print ver
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Code: Alles auswählen

sqlite_module = __import__("sqlite")
conn = sqlite_module.connect(":memory:")
...
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
murph
User
Beiträge: 622
Registriert: Freitag 14. April 2006, 19:23
Kontaktdaten:

das will er nicht!
gleiche fehlermeldung!
Traceback (most recent call last):
File "./sqlite-manager.py", line 103, in ?
starter()
File "./sqlite-manager.py", line 85, in starter
executer.greeting()
File "./sqlite-manager.py", line 91, in greeting
self.conn = sqlite_module.connect(self.conn_var)
NameError: global name 'sqlite_module' is not defined
der code (nicht, dass ich was übersehen habe trotz gründlichen suchens)

Code: Alles auswählen

def Importer():
    getter = UserSettings()
    module = getter.get_module()
    sqlite_module = __import__(module)
class main:
    def greeting(self):
        Importer()
        self.conn_var = raw_input("Please enter the Path to the SQLite-Database: \n")
        self.conn = sqlite_module.connect(self.conn_var)
        self.cur = self.conn.cursor
also meiner ansicht nach sollte das klappen, die variablen sind problemlos vergeben. ich verstehe nicht,warum, wenn gerolds ansatz doch klappen sollte, das nicht funktioniert!
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

murph hat geschrieben:NameError: global name 'sqlite_module' is not defined
Hi murph!

Zwei Sachen:
1. Verwende keine Bindestriche in Modulnamen, da ein Bindestrich für Python ein "Minus" darstellt.
2. Variablen, die du in einer Funktion erstellst -- egal wie -- sind in deren Gültigkeit auf den lokalen Namensraum dieser Funktion beschränkt. Entweder du setzt vor der Verwendung die Variable mit "global" in den globalen Namensraum oder du importierst nicht in einer Funktion.

mfg
Gerold
:-)

PS: Klassennamen sollten mit einem Großbuchstaben beginnen und Funktions-/Methodennamen sollten mit einem Kleinbuchstaben beginnen.

Code: Alles auswählen

class HalloWelt:
    def say_yes(self):
        print "Yes!"
h = HalloWelt() # Sofort als Instanzierung einer Klasse erkennbar
h.say_yes()
Dadurch lassen sich Fehler vermeiden, da man sofort weiß, ob man gerade eben eine Klasse instanziert oder eine Funktion ausführt.
Meines Erachtens, wäre "import_modules()" ein guter Name für die Funktion "Importer()", da er ausdrückt was getan wird. "Importer()" sieht aus wie eine Klasse und hat auch den Namen eines Objektes. Dass keine Klasseninstanz zurück gegeben wird -- verwirrt. :?
Zuletzt geändert von gerold am Freitag 9. Juni 2006, 22:57, insgesamt 1-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Antworten