Seite 1 von 2
Automatisches Auslesen von Dateien und Erstellen einer Neuen
Verfasst: Montag 8. September 2014, 08:27
von Humpalumpa
Hallo Python Forum,
dies ist mein erster Beitrag und schon komme ich mit so einer komischen Frage.
Nun ja, also mein Problem ist folgendes:
Ich habe mehrere .cfg Dateien, die aber nicht der config Formatierung vom Python ConfigParser entsprechen, also ohne [sections] und dafür mit geschweiften und runden Klammern. In etwa so:
Code: Alles auswählen
threads:
{
dmathreads = (
{
id=0; # ThreadID (just for display)
threadname="Worker1"; # Threadname (just for display)
...
} );
Die Dateien beinhalten noch mehr von diesem Kram, aber primär ist für mich das Stichwort "threadname" wichtig.
Ich kann diese Dateien natürlich mit
öffnen und in einen string schreiben. Außerdem danach mit
nach dem Wort suchen.
Ich konnte nur bisher nicht herausfinden, wie ich den Begriff, der "threadname" zugeordnet wird, mir ausgeben lassen kann. Ich habe schon Stunden gesucht und konnte dazu nichts finden.
Leider kann ich auch nicht mit dem ConfigParser arbeiten, da dieser das spezielle Format verlangt. Ich darf jedoch die .cfg Dateien in ihrem Inhalt nicht ändern.
Ich schätze, dass es eine Funktion gibt, mit der ich mir das zugewiesene Wort ausgeben lassen kann. Der Punkt ist, dass ich mehrere dieser Dateien mit variablen Namen und variablen Zuweisungen (also auch variable Stringlänge) automatisch auslesen will, ohne eben die Namen und länge der Dateien und Zuweisungen zu kennen. Leider bin ich bisher nicht besonders weit gekommen, wie man sehen kann.
Mein Code bisher ist dadurch quasi nur:
Wenn ich diese Dateien ausgelesen habe, möchte ich danach automatisch eine Latex Datei erzeugen, die die gefilterten Informationen mit einem bestimmten Kontext enthält. Aber das ist erstmal nebensächlich und es wäre schon eine riesen Hilfe, wenn der erste Teil erstmal steht.
Ich hoffe ihr könnt mir weiterhelfen, da Python für mich neu ist. Dennoch habe ich auch im Manual und im Forum leider vergeblich nach Lösungen gesucht und weiß jetzt nicht mehr weiter. Es ist natürlich möglich, dass ich durch Unwissenheit hilfreiche Beiträge nicht als solche erachtet habe.
Vielen Dank im Voraus,
Humpalumpa
Re: Automatisches Auslesen von Dateien und Erstellen einer N
Verfasst: Montag 8. September 2014, 08:51
von Hyperion
Was für ein Format ist das denn? Wenn es ein gängiges ist, gibt es evtl. schon einen Parser in Python, den man nutzen könnte. Wenn nicht (und Du das Format nicht ändern kannst), musst Du einen eigenen bauen; genau das, was Du letztlich schon versuchst.
Da gibt es mehrere Möglichkeiten; je nach Anwendungsfall sind die unterschiedlich geeignet. Das einfachste Mittel stellen die String-Funktionen von Python dar, danach kämen als Ergänzung reguläre Ausdrücke hinzu und als letztes spezielle Module für das Bauen von Parsern.
Wenn es Dir wirklich nur um die Zeile ``threadname="Worker1";`` geht, kann man das einfach mittels ``str.split`` umsetzen. Schau Dir das mal in der offiziellen Doku an und probiere dann in einer Python-Shell, wie man die Methode sinnvoll einsetzen kann. Ach ja, Indexzugriffe sollte man natürlich dafür kennen - also wirklich nur Basics.
Dateien solltest Du übrigens mittels ``with open(...) as handler_name`` öffnen - damit sparst Du Dir ein explizites ``handler_name.close()``, um die Datei zu schließen und es klappt auch im Fehlerfall garantiert.
Re: Automatisches Auslesen von Dateien und Erstellen einer N
Verfasst: Montag 8. September 2014, 08:57
von mutetella
@Humpalumpa
Wenn die Zeile nicht nur in etwa sondern tatsächlich so aussieht, könntest Du die Methode ``split()`` verwenden:
Code: Alles auswählen
>>> 'threadname="Worker"'.split('=')
['threadname', '"Worker"']
mutetella
Re: Automatisches Auslesen von Dateien und Erstellen einer N
Verfasst: Montag 8. September 2014, 09:02
von Humpalumpa
Danke für die schnelle Antwort.
@Hyperion: Vielen Dank für die ausführliche Antwort, ich werden mir die Split Funktion mal ansehen. Leider finde ich es ziemlich schwierig am Anfang gut voran zu kommen, da man einfach die Bandbreite der ganzen Funktionen noch nicht kennt.
Die Dateien sind als .cfg formatiert, jedoch mit einem eigenen Parser geschrieben, auf den ich keinen Zugriff habe. Aber glücklicherweise funktioniert die einfache "open" Funktion (bzw. mit helper).
@mutella: Mein Problem ist, dass ich nur das Stichwort "threadname" kenne, jedoch nicht den zugewiesenen Namen.
Vermutlich kann man mit der standart Bibliothek "re" etwas anfangen.
Also nachdem ich hier
http://openbook.galileocomputing.de/pyt ... 15_002.htm etwas genauer nachgelesen habe, sieht es so aus als könne man in etwa mit
etwas anfangen. Leider scheint die Syntax so nicht ganz zu funktionieren.
Re: Automatisches Auslesen von Dateien und Erstellen einer N
Verfasst: Montag 8. September 2014, 09:19
von mutetella
@Humpalumpa
Warum eigentlich nicht gleich ein regex? Damit würdest Du Dir auch das Suchen nach der passenden 'threadname=...' Zeile sparen:
Code: Alles auswählen
>>> import re
>>> re.findall(r'threadname="(.*)"', 'threadname="Worker";')
['Worker']
Der reguläre Ausdruck bedeutet: Suche eine Gruppe von Buchstaben beliebiger Anzahl, die innerhalb eines Strings 'threadname="' und einem '"' steht.
mutetella
Re: Automatisches Auslesen von Dateien und Erstellen einer N
Verfasst: Montag 8. September 2014, 09:40
von Humpalumpa
@mutetella
Die findall Funktion scheint ganz gut zu sein, leider muss man dort scheinbar auch den genauen Namen (in diesem Fall "Worker") angeben. Ich brauche jedoch ein Programm, was diesen Namen automatisch herausfindet, nur indem er die Zuweisung und die vorherigen, sowie nachfolgenden Zeichengrenzen kennt (also nur threadname="(hier unbekanntes Wort)").
Mit
Code: Alles auswählen
re.findall(r'threadname="(.*)"', 'threadname="Worker";')
gibt er mir ja nur das aus, was ich im zweiten Segment der findall Funktion angebe. Hast du eine Idee, wie das zu lösen ist?
Ich hätte gern in etwa sowas:
Als Ausgabe dann eben gesuchten threadname.
Bei der str.split() Funtkion kann ich doch auch nur nach bekannten strings suchen, oder hab ich die Falsch verstanden?
Re: Automatisches Auslesen von Dateien und Erstellen einer N
Verfasst: Montag 8. September 2014, 09:45
von /me
Anscheinend hast du dir die Funktion noch nicht wirklich angeschaut.
Hier mal ein Test.
Code: Alles auswählen
>>> import re
>>> re.findall(r'threadname="(.*)"', 'threadname="Worker";')
['Worker']
>>> re.findall(r'threadname="(.*)"', 'threadname="Server";')
['Server']
Re: Automatisches Auslesen von Dateien und Erstellen einer N
Verfasst: Montag 8. September 2014, 09:50
von mutetella
Humpalumpa hat geschrieben:Ich hätte gern in etwa sowas:
Ehrlich gesagt verstehe ich nicht wirklich, was Du denn möchtest? Es schaut so aus, als würdest Du ein `Worker` Objekt als Rückgabe benötigen? Dafür müsstest Du aus dem String 'Worker' oder was immer auch als Ergebnis da ist, ein Objekt erstellen. `getattr()` fällt mir dazu ein oder ein Mapping, das Dir ein gewünschtes Objekt zurückgibt.
mutetella
Re: Automatisches Auslesen von Dateien und Erstellen einer N
Verfasst: Montag 8. September 2014, 09:56
von Humpalumpa
mutetella hat geschrieben:
Ehrlich gesagt verstehe ich nicht wirklich, was Du denn möchtest? Es schaut so aus, als würdest Du ein `Worker` Objekt als Rückgabe benötigen? Dafür müsstest Du aus dem String 'Worker' oder was immer auch als Ergebnis da ist, ein Objekt erstellen. `getattr()` fällt mir dazu ein oder ein Mapping, das Dir ein gewünschtes Objekt zurückgibt.
mutetella
Hi mutetella,
danke für deine tatkräftige Unterstützung. Scheinbar habe ich mich falsch ausgedrückt. Tut mir leid, wenn ich bei euch verwirrung gestiftet habe.
Ich brauche tatsächlich nur den Rückgabewert, der "threadname=" zugewiesen wird.
Ich schaue mir mal "getattr()" an. Vielen Dank schomal.
Re: Automatisches Auslesen von Dateien und Erstellen einer N
Verfasst: Montag 8. September 2014, 10:07
von mutetella
@Humpalumpa
Einfach mal noch als Anregung, weil ich tatsächlich noch nicht wirklich weiß, was Du möchtest...:
Code: Alles auswählen
>>> class Worker(object):
... ANY_ATTR = 'any attr'
...
>>> class Server(object):
... pass
...
>>> objects = {'Worker': Worker, 'Server': Server}
>>> w = objects['Worker']
>>> w
<class '__main__.Worker'>
>>> getattr(w, 'ANY_ATTR')
'any attr'
mutetella
Re: Automatisches Auslesen von Dateien und Erstellen einer N
Verfasst: Montag 8. September 2014, 10:23
von Humpalumpa
@mutetella
Okay, ich glaube ich habs wirklich schlecht erklärt. Sorry
Ein neuer strukturierter Versuch:
Ich habe mehrere Dateien, wie in etwa:
- datei1.cfg
- datei2.cfg
- datei3.cfg
Diese sind vom Inhalt unterschiedlich, haben aber alle eine Zuweisung mittels:
Dabei steht xxx für den unbekannten Zuweisungsnamen, der bei jeder Datei anders ist.
Dieser kann sein "Worker1", "cpurun", etc.
Ich kenne den Inhalt von xxx nicht, will ihn nun aber herauslesen und in eine neue Datei schreiben.
Und das bei einer unbekannten Anzahl von Dateien. (Dies lässt sich dann aber über eine Schleife realisieren.)
Mein primäres Problem ist, dass ich nur die Grenzen, in denen xxx liegt kenne, jedoch nicht den Inhalt.
Deshalb, um das Programm auf alle Dateien anwenden zu können, kann ich keinen konkreten Suchinhalt angeben, sondern nur den Bereich, indem er liegt (eben genanntes [threadname=" "]).
Ich hoffe, dass das jetzt irgendwie verständlich und nicht noch verwirrender ist.

Re: Automatisches Auslesen von Dateien und Erstellen einer N
Verfasst: Montag 8. September 2014, 10:29
von mutetella
@Humpalumpa
Ok, dann hast Du ja jetzt alle Werkzeuge zur Hand, die Du benötigst. Damit gehst Du nun Zeile für Zeile jeder Datei durch (``for line in file:``) und ziehst die gewünschten Strings heraus.
mutetella
Re: Automatisches Auslesen von Dateien und Erstellen einer N
Verfasst: Montag 8. September 2014, 10:38
von Humpalumpa
/me hat geschrieben:Anscheinend hast du dir die Funktion noch nicht wirklich angeschaut.
Hier mal ein Test.
Code: Alles auswählen
>>> import re
>>> re.findall(r'threadname="(.*)"', 'threadname="Worker";')
['Worker']
>>> re.findall(r'threadname="(.*)"', 'threadname="Server";')
['Server']
Hallo /me,
doch ich habe sie genau so verstanden, wie dein Beispiel zeigt. Das Problem ist, dass ich eben den zugewiesenen String von threadname nicht kenne.
Re: Automatisches Auslesen von Dateien und Erstellen einer N
Verfasst: Montag 8. September 2014, 10:43
von mutetella
Humpalumpa hat geschrieben:Das Problem ist, dass ich eben den zugewiesenen String von threadname nicht kenne.
Musst Du ja auch nicht. Den liefert Dir `findall()` ja. Und dann hast Du ihn!
mutetella
Re: Automatisches Auslesen von Dateien und Erstellen einer N
Verfasst: Montag 8. September 2014, 10:48
von Humpalumpa
mutetella hat geschrieben:@Humpalumpa
Ok, dann hast Du ja jetzt alle Werkzeuge zur Hand, die Du benötigst. Damit gehst Du nun Zeile für Zeile jeder Datei durch (``for line in file:``) und ziehst die gewünschten Strings heraus.
mutetella
Okay mutetella, scheinbar bist du schlauer als ich. Ich kann gerade keine sinnvolle Verbindung ziehen.
Kannst du mir evtl ein konkretes Beispiel geben? Sorry, wenn das nervig erscheinen sollte, aber ich weiß im Moment nicht, wie ich "for line in file" nutzen kann. :K
Ich habe es so probiert:
Code: Alles auswählen
string1 = 'threadname=""' for line in file:'datei1.cfg'
Was leider nicht funktioniert, weil vermutlich etwas fehlt oder syntaktisch falsch ist.
Ich kann mittels re.findall doch nur konkrete Strings suchen oder?
Es funktioniert ja schließlich nicht, wenn ich nur
eingebe.
Denn
Code: Alles auswählen
re.findall(r'threadname="(.*)"','threadname="Worker"')
kann ich nicht nutzen, da ich den string "Worker" nicht kenne und er je nach Datei anders heißt.
Re: Automatisches Auslesen von Dateien und Erstellen einer N
Verfasst: Montag 8. September 2014, 11:02
von mutetella
@Humpalumpa
Uiuiui, da fehlen Dir aber doch ein paar Basics. Ich empfehle Dir, einmal das offizielle
Python Tutorial durchzuarbeiten...
Humpalumpa hat geschrieben:Ich kann mittels re.findall doch nur konkrete Strings suchen oder?
Na eben nicht, denn hättest Du einen "konkreten String", dann müsstest Du ihn ja nicht suchen, oder? Ein regulärer Ausdruck ist letztlich ein Schema, das auf einen String angewendet wird. Das Ergebnis ist dann all das, das auf das Schema passt.
Die Funktion `findall()` erwartet 2 Argumente. Erstens den regulären Ausdruck, also das Schema. Zweitens den String, der durchsucht werden soll. In unseren Beispielen haben wir ja nur der Einfachheit halber dort einen "konkreten String" angegeben. Natürlich wird später einmal an dessen Stelle ein Name stehen, in etwa sowas:
Code: Alles auswählen
with open(filename, 'r') as file:
for line in file:
result = re.findall(r'threadname="(.*)"', line)
...
mutetella
Re: Automatisches Auslesen von Dateien und Erstellen einer N
Verfasst: Montag 8. September 2014, 11:02
von Sirius3
@Humpalumpa: um das ganze abzukürzen:
Code: Alles auswählen
with open('datei.cfg') as cfg:
threadnames = re.findall('threadname="(.*?)"', cfg.read())
Und jetzt finde den Unterschied zu Deinen Versuchen.
Re: Automatisches Auslesen von Dateien und Erstellen einer N
Verfasst: Montag 8. September 2014, 11:20
von Humpalumpa
mutetella hat geschrieben:
Die Funktion `findall()` erwartet 2 Argumente. Erstens den regulären Ausdruck, also das Schema. Zweitens den String, der durchsucht werden soll. In unseren Beispielen haben wir ja nur der Einfachheit halber dort einen "konkreten String" angegeben. Natürlich wird später einmal an dessen Stelle ein Name stehen, in etwa sowas:
Code: Alles auswählen
with open(filename, 'r') as file:
for line in file:
result = re.findall(r'threadname="(.*)"', line)
...
mutetella
Ahaa, jetzt verstehe ich. Tut mir leid, das hat lange gedauert, ich habe jetzt auch das richtige schonmal rausbekommen. Vielen vielen Dank!
Ja ich bin noch ein ziemlicher Newbie im Programmieren und Python hab ich vor 5 Jahren in der Schule gehabt. Jetzt komme ich nicht drum herum, lerne hier aber viel dazu. Das Tutorial hab ich mir auch mal angesehen, aber habe nicht alles gelesen. Mir wurde beigebracht immer nur nach dem zu suchen, was man braucht, anstatt erstmal so einen Berg an Informationen durchzuarbeiten. Ich weiß selbst noch nicht, welcher Ansatz besser ist.
Also noch einmal: Vielen Dank!
Ich werde jetzt erstmal Mittagspause machen und mich dann dran setzen. Ich halte euch auf dem Laufenden und auch, falls woanders noch Fragen auftreten sollten.

Re: Automatisches Auslesen von Dateien und Erstellen einer N
Verfasst: Montag 8. September 2014, 14:51
von Humpalumpa
Hallo nochmal,
wie bereits gesagt, habt ihr mir sehr geholfen.
Ich habe nun quasi das umgekehrte Problem.
Ich kann nun die einzelnen Wörter aus den Dateien auslesen, will nun aber erstmal die gewünschten Dateien auswählen.
Dazu gebe ich einen Pfad ein und lasse mir mittels
die vorhandenen Dateien anzeigen. Dort sind nun aber auch andere Dateien drin und nicht nur .cfg.
Ich habe jetzt versucht mittels:
Code: Alles auswählen
inventory = os.listdir(directory)
inventstr = ' '.join(inventory)
print 'Es werden folgende Dateien ausgelesen: ', re.findall(r'(.*?).cfg', inventstr)
die Dateien zu separieren, um danach auf sie zugreifen und auslesen zu können.
Leider funktioniert dies nur mit der .cfg Datei, die an erster Stelle im Ordner kommt, durch die r'()' Syntax. Mir ist bisher keine Lösung eingefallen und ich habe schon einiges probiert. Ich hatte gehofft, durch das Fragezeichen diese lange Kette vermeiden zu können, ist jedoch nicht ganz gelungen.
Die Liste 'inventory' kann ich so scheinbar nicht auslesen. Deshalb konvertiere ich sie in einen string mittels ' '.join(inventory). Dabei dachte ich, dass es wohl sinnvoller ist, wenn zwischen den Dateinamen ein Leerzeichen ist, deshalb beim join das Leerzeichen.
Das klappt aber auch nicht so gut, da dann folgendes raus kommt:
Datei1 ist korrekt, aber XDatei2 eben nicht. Ich weiß, dass es an der r'()' Abfrage liegt, weiß aber nicht, wie ich diese so gestalten kann, dass das gewünschte ergebnis dabei heraus kommt.
Kann mir da jemand helfen?
Humpalumpa
Re: Automatisches Auslesen von Dateien und Erstellen einer N
Verfasst: Montag 8. September 2014, 15:10
von EyDu
Die Lösung ist auch wieder die selbe wie vorher. Benutze eine for-Schleife über "inventory" und teste dort die Endung. Der Umgang mit so elementaren Datenstrukturen gehört zu den absoluten Grundlagen, dein Ansatz sieht mehr nach Raten aus. Vielleicht solltest du noch einmal das Tutorial in der Pythondokumentation durcharbeiten.
Ansonsten gibt es auch noch das glob-Modul.