Seite 1 von 1

Arraywerte aus einer externen Datei laden

Verfasst: Dienstag 19. Januar 2010, 19:48
von hosch
Hallo,

ich möchte mit einem Script die Konfigurationswerte einer Xen-Installation auslesen.

Die Konfig schaut folgendermaßen aus:
kernel = '/boot/vmlinuz-2.6.26-2-xen-amd64'
#kommentar
ramdisk = '/boot/initrd.img-2.6.26-2-xen-amd64'
memory = '1024'
vcpus='8'
root = '/dev/sda1 ro'
disk = [
'file:/var/disk.img,sda1,w',
]
name = 'node123'
dhcp = 'dhcp'
vif = [ 'mac=00:16:3E:43:DF:D8' ]
Gibt es eine Möglichkeit, die Datei direkt in eine Konfig-Variable zu laden? Ich habe bisher nur Config-Module für csv, xml, usw. gefunden, nichts jedoch, dass das oben gezeigte Format lädt.

Verfasst: Dienstag 19. Januar 2010, 19:52
von IoI
Versuchs mal mit ConfigParser

Verfasst: Dienstag 19. Januar 2010, 19:53
von Pekh
Schau dir mal das Modul ConfigParser an. Und das Tutorial ;) Das was du als Array bezeichnest, ist nämlich mit ziemlicher Sicherheit ein Dictionary oder eine Liste.

Verfasst: Mittwoch 20. Januar 2010, 00:57
von hosch
Pekh hat geschrieben:Schau dir mal das Modul ConfigParser an. Und das Tutorial ;) Das was du als Array bezeichnest, ist nämlich mit ziemlicher Sicherheit ein Dictionary oder eine Liste.
Das Modul hab ich mir schon angesehen. ConfigParser verwendet jedoch eine leicht andere Struktur (es gibt bei der xen-config z.b. keine section). Außerdem werden die Variablen nicht korrekt geladen [wenn ich die section händisch einfüge] z.b werden Substrukturen nicht geparst außerdem wird bei Wertzuweisungen ala
key='asdf'
das Hochkomma nicht entfernt.

Verfasst: Mittwoch 20. Januar 2010, 01:30
von cofi
Wenn das denn - wie es aussieht - gueltige Python-Syntax ist, kannst du es auch als Modul laden, eventuell auch AST aber das waeren Kanonen.

Verfasst: Mittwoch 20. Januar 2010, 07:47
von Michael Schneider
Moin,

entschuldigt, wenn ich mich wieder als Ahnungsloser in Config-Objekten zu Wort melde. Aber wenn es gültige Python Syntax ist, kann man sie auch mit exec in einem leeren Dictionary als Namensraum ausführen:

Code: Alles auswählen

s = """kernel = '/boot/vmlinuz-2.6.26-2-xen-amd64'
#kommentar
ramdisk = '/boot/initrd.img-2.6.26-2-xen-amd64'
memory = '1024'
vcpus='8'
root = '/dev/sda1 ro'
disk = [
'file:/var/disk.img,sda1,w',
]
name = 'node123'
dhcp = 'dhcp'
vif = [ 'mac=00:16:3E:43:DF:D8' ]"""

dummy, result = {}, {}
exec s in dummy, result
print result
{'ramdisk': '/boot/initrd.img-2.6.26-2-xen-amd64', 'kernel': '/boot/vmlinuz-2.6.26-2-xen-amd64', 'vif': ['mac=00:16:3E:4
3:DF:D8'], 'name': 'node123', 'vcpus': '8', 'memory': '1024', 'dhcp': 'dhcp', 'disk': ['file:/var/disk.img,sda1,w'], 'ro
ot': '/dev/sda1 ro'}
dummy habe ich verwendet, da im ersten Dict (zumindest meist) ein __builtins__ angelegt wird. Statt des Dummys hätte man auch nachträglich prüfen können, ob __builtins__ im Dict ist und es gegebenermaßen entfernt. Dies war die kurze Variante, aber speicheraufwendiger.

Grüße,
Michel

Verfasst: Mittwoch 20. Januar 2010, 09:27
von da.dom
Michael Schneider hat geschrieben: dummy, result = {}, {}
exec s in dummy, result
print result[/code]
Sehr chick, kannte ich auch nocht nicht (Tagwerk vollbracht, wieder was gelernt).

a) Kann mir jemand noch mal genauer erklären was in dem ersten dict landet? Sind das die buildin objekte die er global ablegt? (hab in der API was von global und local variablen gelesen

b) der optionale Parameter "in" ist mir in diesem Fall nicht ganz klar geworden, er definiert den Scope in dem das ganze ausgeführt werden soll. Was er in diesem Fall macht sieht man ja, aber gibt es da noch andere Anwedungsszenarien für den Parameter, ausser dict's aus Strings zu parsen?

Danke schon mal für eine mögliche Erklärung :)

Grüße
D

Verfasst: Mittwoch 20. Januar 2010, 16:07
von hosch
Michael Schneider hat geschrieben: dummy, result = {}, {}
exec s in dummy, result
Danke!
Diese 2 Zeilen sind genau das, was ich gesucht habe :)
Hab ich mir doch gedacht, dass ich keinen eigenen Parser dafür schreiben muss.

Verfasst: Donnerstag 21. Januar 2010, 00:34
von Michael Schneider
Hallo D!
da.dom hat geschrieben:a) Kann mir jemand noch mal genauer erklären was in dem ersten dict landet? Sind das die buildin objekte die er global ablegt? (hab in der API was von global und local variablen gelesen
Ja, Python unterscheidet zwischen zwei Namensräumen, dem Globalen und dem Lokalen. Um diese zu simulieren, werden bis zu zwei Dictionaries benötigt. Wenn exec beispielsweise eine Funktion ausführt, in der bestimmte globale Namen definiert werden, dann werden Änderungen daran im globalen Dict durchgeführt, sonst im lokalen.

Wie das __builtins__ nun ausgerechnet in das anfangs leere, globale Dict kommt, kann ich nicht genau sagen. Es wird aber damit zusammenhängen, dass diese Variablen immer global definiert sind, um auf die Grundfunktionen überhaupt zugreifen zu können.
da.dom hat geschrieben:b) der optionale Parameter "in" ist mir in diesem Fall nicht ganz klar geworden, er definiert den Scope in dem das ganze ausgeführt werden soll. Was er in diesem Fall macht sieht man ja, aber gibt es da noch andere Anwedungsszenarien für den Parameter, ausser dict's aus Strings zu parsen?
Nicht das 'in', sondern das 'exec' führt den String so aus, als ob es Quelltext in einer Python-Quellcodedatei ist. Eine Angabe von dictionaries ist nicht notwendig und wenn weggelassen wird der Code in den aktuellen Namensräumen ausgeführt. Das ist die wahrscheinlich mächtigste Funktion, da sie sich selbst generierenden Code dynamisch ausführen und so zu teuflischen Ergebnissen führen kann, gelinde gesagt. Deshalb sollte man eine Ausführung im aktuellen Namensraum tunlichst vermeiden und außerdem brauchst Du die eingelesenen Variablen ja sowieso in einem Dict.

'in' dient in diesem Fall, ebenso wie in 'enthält'-Prüfungen a la

Code: Alles auswählen

key in dict
, als Schlüsselwort in einem fest definierten Konstrukt. In letzterem Fall bewirkt es einen Aufruf der dict-Methode __contains__ mit key als Argument. Allein kann es aber niemals eine Funktion ausführen.

Ich hoffe, das beantwortet das eine oder andere.

LG,
Michel

Verfasst: Freitag 22. Januar 2010, 13:42
von da.dom
HuHu..

danke erst mal für deine ausfürliche Antwort. Das mit dem exec war mir schon mal klar, aber nur damit ich das richtig verstehe wiederhole ich mal (mit der Bitte auf Korrektur, falls was falsch ist):

Alles Variablen, Objekte und Methoden werden im Hintergrund in dictionaries abgelgt: locals() und globals() sind das? Wenn ich also eine in meinem Programm definiere, fügt er diese dem locals-dictionary einen Eintrag hinzu.. (variable='test' entspricht demnach so was wie: locals()['variable']='test'?!)

Sprich wenn ich die Datei ohne "Scope" angabe ausführe:

Code: Alles auswählen

...
exec s
print memory
...
Nutz er als "Standard" (?) Scope für Programme das locale dict und ich kann auf die Variablen direkt zugreifen. Mit der zusätzlichen Anweisung "in" gebe ich ihm aber einen expliziten Scope mit (laut API)...ok...in diesem Fall verstehe ich was er dann tut, wobei ich eher so was erwartet hätte:

Code: Alles auswählen

exec s in myDict
Viele Grüße
Dom