Variableninhalt ausführen

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.
Antworten
api
User
Beiträge: 181
Registriert: Donnerstag 7. August 2008, 21:23

Hallo zusammen,

eventuell ne ganz einfache Frage (bzw. Antwort). Ich habe folgenden Programmcode:

Code: Alles auswählen

import os

test = 'os.path.join("/tmp", "test")'

print test
Die Ausgabe zur Zeit ist:
os.path.join("/tmp", "test")

Ist ja auch verständlich. Wie aber kann ich den Code in der Variablen ausführen? Also, dass das Ergebnis dann so aussieht?

/tmp/test

CU,
API
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Nun, `eval` tut das.

Die Sicherheitsaspekte sollten dir aber klar sein, eine sichere Version laesst sich ueber `ast` bauen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Wobei Du uns durchaus mal genauer erläutern solltest, was Du da genau planst. Evtl. gibt es da ja auch einen anderen Weg.

Von eval() ist grundsätzlich abzuraten.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
api
User
Beiträge: 181
Registriert: Donnerstag 7. August 2008, 21:23

Hallo cofi,

danke für die schnelle Antwort - das ist das, was ich suchte... :D

Aber kannst du mir kurz dein Statement zu 'ast' erklären? Was ist an der obigen Anweisung nicht sicher?

Hyperion: Ich lese aus einer config.ini einen Pfad ein - also diesen String - und möchte ihn im Prg nun nutzen, natürlich als Datei-Pfad.
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

*g da ist dir ein kleiner Fehler unterlaufen:

Es muss heißen:

Code: Alles auswählen

import os

test = os.path.join("/tmp", "test")

print test
Funktionen sollten niemals in Anführungsstrichen stehen - sonst erhälst du einfach nur einen String, ohne dass irgendwas getan wird.

Gruß,

brb
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

api hat geschrieben: Hyperion: Ich lese aus einer config.ini einen Pfad ein - also diesen String - und möchte ihn im Prg nun nutzen, natürlich als Datei-Pfad.
Das Scenario birgt jede Menge Gefahren in sich... stell Dir vor da schreibt einer ein Python-Script in die Datei, die schlimme Dinge anstellt (Dateien löschen, usw) Das eval() würde das einfach ausführen.

Ich kapiere da noch nicht, was Du da eigentlich vor hast. Wieso musst Du da ein Python-Statement als String ablegen? Da müßtest Du doch noch mal ein wenig deutlicher werden.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
lunar

@api: Denk doch nach. Man kann dann jede beliebige Anweisung in diese Datei schreiben, Dein Programm wird sie anstandslos ausführen ... die daraus resultierenden Probleme sind doch eigentlich offensichtlich, oder?

Wieso muss der Nutzer überhaupt Quelltext eingeben, um einen Pfad in die Konfigurationsdatei einzutragen? Er kann doch einfach direkt den richtigen Pfad hinschreiben ...

@Barabbas: Das war ein Beispiel :roll:
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

api hat geschrieben:Aber kannst du mir kurz dein Statement zu 'ast' erklären? Was ist an der obigen Anweisung nicht sicher?
`eval` wertet beliebigen Code aus, gerade bei deinem Anwendungsfall ist das mit Vorsicht zu geniessen, evtl sind 2 Variablen besser: eine fuer den Basisordner und eine fuer die Datei.

Zu ast: http://docs.python.org/library/ast.html

Die Forensuche ist da auch hilfreich, AFAIR hatte sma schon mal ein Beispiel gepostet.
BlackJack

@api: Warum steht in einer Konfigurationsdatei diese Zeichenkette bei einer Pfadangabe? Warum steht da nicht gleich '/tmp/test' drin? Entweder Du hast eine Konfigurationsdatei im Ini-Format, oder Du legst Deine Konfiguration als Python-Modul an, das man dann einfach importieren kann. Mischen von beidem ist keine gute Idee.
api
User
Beiträge: 181
Registriert: Donnerstag 7. August 2008, 21:23

Hallo zusammen,

ich habe vor, wiederkehrende Angaben (also von mehreren Programmen genutzt) in ein ini-File auszulagern, dass dann wie folgt aussieht:

Code: Alles auswählen

.
.
[FILES]
prot_file=os.path.join(LOG_DIR, ProgramName[0] + ".prot")
.
.
Das dann per ConfigParser ausgelesen - hätte ich das Protokoll-File. Brauch das also nicht immer bei jedem Prg neu zu schreiben.
Zu der Frage, warum ich nicht den Pfad hardcoded reinschreibe? Das LOG_DIR kann durchaus unterschiedlich sein - ganz zu schweigen vom Programmnamen.

Zugriff auf diese Datei hat kein User, der nicht weiss, was er da tut (so die Theorie! :D )

Ansonsten gebe ich euch natürlich recht, einfach Programmcode auszuführen, ohne zu wissen, was drinsteht, wäre ein bischen arg gefährlich.
BlackJack

@api: Das ist aber IMHO noch kein Grund da ausführbaren Python-Quelltext als Wert hineinzuschreiben. Man könnte auch einfach Platzhalter definieren, die dann zum Beispiel mittels `string.Template` ersetzt werden.

Code: Alles auswählen

prot_file=$LOG_DIR/$ProgramName.prot
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

lunar hat geschrieben:@Barabbas: Das war ein Beispiel :roll:
*räusperhust* ups - weiß auch nicht, welche Synapsen da gerade bei mir verklebt waren /:
api
User
Beiträge: 181
Registriert: Donnerstag 7. August 2008, 21:23

@BlackJack: Ich hab mich mal mit dem string.Template beschäftigt. Ob ich es so einsetze, kann ich im Augenblick noch nicht abschätzen - aber ein guter Ansatz... :wink:

Auf jeden Fall nehme ich Abstand von 'eval()' - eher werde ich eine Art einer Ersetzung wählen.

Danke euch für eure Hilfe.
Benutzeravatar
b.esser-wisser
User
Beiträge: 272
Registriert: Freitag 20. Februar 2009, 14:21
Wohnort: Bundeshauptstadt B.

Für ini-style Dateien gibts doch das ConfigParser-Modul, das kann doch sowieso Platzhalter verwenden (Mit der alten "%(name)s"-Syntax).

hth, Jörg
Antworten