daten auslesen und bearbeiten

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.
juju
User
Beiträge: 47
Registriert: Dienstag 25. Mai 2010, 16:02

hellas,

folgendes Problem:

Das von mir zu schreibende Programm soll in der Lage sein aus mehreren definierten Ordnern nur die XML Dateien (jede XML hat den gleichen Aufbau) zu wählen und daraus spezielle Werte (klappt soweit)...

nun schreibt das Programm für jede XML-Datei eingene Listen (siehe Quellcode) ... ich möchte aber gerne, dass alle Listen für z.B. R1I1o in der gleichnamigen Liste abgespeichert werden, sprich; das Programm soll alle Einzellisten von R1I1o in eine Gesamtliste R1I1o packen, um sie anschließend seperat bearbeiten zu können.

Kann mir da jemand weiter helfen??

Code: Alles auswählen

def process(insert_file):
	xml = open(insert_file, "r")
	data = xml.readlines() 
	xml.close()

	R1I1o=[]
	R2I1o=[]
	R3I1o=[]
	R4I1o=[]
	R1I1t=[]
	R2I1t=[]
	R3I1t=[]
	R4I1t=[]
	R1I2o=[]
	R2I2o=[]
	R3I2o=[]
	R4I2o=[]
	R1I2t=[]
	R2I2t=[]
	R3I2t=[]
	R4I2t=[]


	num_liste = str(enumerate(data))    			# string as tuple fixed to i

	for i, wert in enumerate(data):					# get value of interest
		if i == 25:									# filter
			status = wert
			status = status.strip()
			status = str(status[27:32])
		
			if status == "Error":
				print status
				break
			else:
				for i, wert in enumerate(data):
					if i == 77:						# co R1 I1			
						c11_off = wert					
						c11_off = c11_off.strip()
						c11_off = (c11_off[6:9])								
						R1I1o.append(c11_off)	
						
					if i == 89:						# ct R1 I1
						c11_tre = wert
						c11_tre = c11_tre.strip()
						c11_tre = (c11_tre[6])
						R1I1t.append(c11_tre)

					if i == 104:					# co R2 I1 
						c21_off = wert
						c21_off = c21_off.strip()
						c21_off = (c21_off[6:9])
						R2I1o.append(c21_off)
						
					if i == 116:                    # ct R2 I1
						c21_tre = wert
						c21_tre = c21_tre.strip()
						c21_tre = (c21_tre[6])
						R2I1t.append(c21_tre)
						
					if i == 131:					# co R3 I1
						c31_off = wert
						c31_off = c31_off.strip()
						c31_off = (c31_off[6:9])
						R3I1o.append(c31_off)

					if i == 143:					# ct R3 I1
						c31_tre = wert
						c31_tre = c31_tre.strip()
						c31_tre = (c31_tre[6:8])
						R3I1t.append(c31_tre)
						
					if i == 158:					# co R4 I1
						c41_off = wert
						c41_off = c41_off.strip()
						c41_off = (c41_off[6:9])
						R4I1o.append(c41_off)
						
					if i == 170:					# ct R4 I1
						c41_tre = wert
						c41_tre = c41_tre.strip()
						c41_tre = (c41_tre[6:9])
						R4I1t.append(c41_tre)
						
					if i == 199:					# co R1 I2
						c12_off = wert
						c12_off = c12_off.strip()
						c12_off =(c12_off[6:9])
						R1I2o.append(c12_off)
						
					if i == 211:					# ct R1 I2
						c12_tre = wert
						c12_tre = c12_tre.strip()
						c12_tre = (c12_tre[6])
						R1I2t.append(c12_tre)
						
					if i == 226:					# co R2 I2
						c22_off = wert
						c22_off = c22_off.strip()
						c22_off = (c22_off[6:9])
						R2I2o.append(c22_off)
						
					if i == 238:					# ct R2 I2
						c22_tre = wert
						c22_tre = c22_tre.strip()
						c22_tre = (c22_tre[6])
						R2I2t.append(c22_tre)
						
					if i == 253:					# co R3 I2
						c32_off = wert
						c32_off = c32_off.strip()
						c32_off = (c32_off[6:9])
						R3I2o.append(c32_off)
						
					if i == 265:					# ct R3 I2
						c32_tre = wert
						c32_tre = c32_tre.strip()
						c32_tre = (c32_tre[6:8])
						R3I2t.append(c32_tre)
						
					if i == 280:					# co R4 I2
						c42_off = wert
						c42_off = c42_off.strip()
						c42_off = (c42_off[6:9])
						R4I2o.append(c42_off)
						
					if i == 292:					# ct R4 I2
						c42_tre = wert
						c42_tre = c42_tre.strip()
						c42_tre = (c42_tre[6:9])
						R4I2t.append(c42_tre)

	print R1I1o, R1I1t, R2I1o, R2I1t, R3I1o, R3I1t, R4I1o, R4I1t, R1I2o, R1I2t, R2I2o, R2I2t, R3I2o, R3I2t, R4I2o, R4I2t


input = sys.argv[1].strip(chr(34))					
flagRecursive = True
outputList = []

if flagRecursive == True:
	for root, dirs, files in os.walk(input):
		outputList.append(root)
	 
		for f1 in files:
			outputList.append('/'.join([root, f1]))
else:
	outputList = os.listdir(".")
	
filepattern = re.compile(".*xml$", re.IGNORECASE)

for item in outputList:
	if filepattern.match(item) and os.path.isfile(item):
		process(item)
		
os._exit(0)

Danke schonmal

Grüße
Julian
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo und willkommen im Forum!

Erstmal solltest du deinen Code kürzen. Wenn du Namen durchnummerierst, dann willst du Listen, Tupel oder Dictionaries verwenden. Das gilt besonders für deine 16 Listen.

Und wenn du copy&paste verwendest, dann machst du grundsätzlich etwas falsch:

Code: Alles auswählen

FOO = {
  77: (R1I1o, slice(6, 9)),
  89: (R1I1t, slice(6)),
  ...
}

for i, wert in  enumerate(data):
  r, off = FOO[i]
  r.append(wert[off])
   ...
Und denke mal über das

Code: Alles auswählen

flagRecursive == True
nach. Was liefert dieser Ausdruck wohl als Ergebnis und warum testest du ihn nicht auf True ;-)

Natürlich möchtest du auch keine globalen Variablen oder Code auf Modulebene. PEP8 hingegen möchtest du einhalten und lieber 4 Leerzeichen verwenden als Tabs ;-)
Das Leben ist wie ein Tennisball.
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Tja... Du machst fast alles falsch, was man nur falsch machen kann. Ich weiß gar nicht, wo ich anfangen soll.

1) Warum nutzt du XML Dateien nicht als das, was sie sind: Maschinenlesbare Datenstrukturen.
2) Lerne, dictionaries zu benutzen. Copy&Paste Code ist immer ein deutliches Zeichen, das da was nicht stimmt.
3) Warum iterierst du über jede einzelne Zeile deiner Daten, wenn du genau weist, das du Zeile 77 haben willst? Was soll das?

Schreib es neu und lass dir dabei von uns helfen. Aber mit DEM Skript da kommst du nicht weit.
Bottle: Micro Web Framework + Development Blog
juju
User
Beiträge: 47
Registriert: Dienstag 25. Mai 2010, 16:02

oh ...danke schonmal für die schnellen antworten... glaube ich gerne, dass der code nicht dem enstpricht, was man unter "Programmieren" versteht... aus dem Grund bin ich ja auf der Suche nach Hilfe ;) ... aber scheinbar bin ich hier ja an der richtigen Stelle :)

... ich arbeite mit Python (ver. 2.6 wegen matplotlib etc) erst seit ungefähr drei Wochen...entsprechend habe ich momentan noch zu wenig Kenntnisse, um das zu programmieren, was ich mir vorstelle.. bin aber fleißig am arbeiten ...

die XML Datei die ich hier verwende hat keine value oder key tags oder ähnliches... im Prinzip baut sie eine Tabelle auf (es gibt also fast ausschließlich cell und row tags) -> aus diesem Grund habe ich die Zeilen auch durchiteriert, um sie einzeln ansprechen zu können... Parser konnte ich wegen den Zellen und Reihen leider nicht erfolgreich verwenden...

im Prinzip soll das Programm die relevanten Bereiche (Zahlenwerte) aus allen vorgegebenen Dateien in 16 Listen schreiben und dann Mittelwert, Standardabw etc der einzelnen Listen bilden... das war meine Aufgabenstellung... ich habe dann einfach angefangen... da ich nun ohne Hilfestellungen nicht mehr weiterkomme, habe ich mich hier angemeldet...

klar ist copy und paste mist...mir fehlen halt momentan die befehle etc...
Dingels
User
Beiträge: 61
Registriert: Dienstag 23. Dezember 2008, 19:50

Hallo juju,

sorry, aber aus deinen bisherigen Erklärungen wird man kaum schlau. Könntest Du bitte mal den Inhalt einer deiner XML-Dateien hier posten und nochmals erklären, was genau du daraus extrahieren möchtest?
juju
User
Beiträge: 47
Registriert: Dienstag 25. Mai 2010, 16:02

hier ein kurzer Auschnitt aus der Datei...

Code: Alles auswählen

<Report>
  <Abstract>
    <Heading Level="4">Irgendwas</Heading>
    <Table>
      <Row>
        <Cell>Gebäude</Cell>
        <Cell>
          <Data ID="Gebäude">Haus</Data>
        </Cell>
      </Row>
      <Row>
        <Cell>Benutzer:</Cell>
        <Cell>
          <Data ID="UserName">Juju</Data>
        </Cell>
      </Row>
      <Row>
        <Cell>Procedure Name:</Cell>
        <Cell>
          <Data ID="ProcedureName">Liste von Zahlen</Data>
        </Cell>
      </Row>
      <Row>
        <Cell>Procedure Status:</Cell>
        <Cell>
		<Data ID="ProcedureStatus">fertig</Data>
        </Cell>
      </Row>
      <Row>
        <Cell>Execution Time:</Cell>
        <Cell>
          <Data ID="ExecutionTime" Type="DateTime">Datum</Data>
        </Cell>
      </Row>
      <Row>
        <Cell>Expiration Time:</Cell>
        <Cell>
          <Data ID="ExpirationTime" Type="DateTime">Datum</Data>
        </Cell>
      </Row>
      <Row>
        <Cell>
          <HyperLink>
            <Url>Real.xml</Url>
            <DisplayText>XML Report File</DisplayText>
          </HyperLink>
        </Cell>
        <Cell>
          <HyperLink>
            <Url>Real.pdf</Url>
            <DisplayText>PDF Report File</DisplayText>
          </HyperLink>
        </Cell>
      </Row>
    </Table>
  </Abstract>
  <Heading Level="1">Liste von Zahlen</Heading>
  <Para>Der Nutzer hat etwas unterbrochen</Para>
  <Table Border="true">
    <Caption>Maus1</Caption>
    <Row IsHeading="true">
      <Cell>Nummer</Cell>
      <Cell>a</Cell>
      <Cell>b</Cell>
      <Cell>c</Cell>
      <Cell>d</Cell>
      <Cell>e</Cell>
      <Cell>f</Cell>
      <Cell>g</Cell>
      <Cell>h</Cell>
    </Row>
    <Row>
      <Cell>1</Cell>
      <Cell>
        <Data>641</Data>
      </Cell>
      <Cell>
        <Data>640</Data>
      </Cell>
      <Cell>
        <Data>n.a.</Data>
      </Cell>
      <Cell>
        <Data>620</Data>
      </Cell>
      <Cell>
        <Data>3</Data>
      </Cell>
      <Cell>
        <Data>3</Data>
      </Cell>
      <Cell>
        <Data>n.a.</Data>
      </Cell>
      <Cell>
        <Data>3</Data>
.
.
.
zur Erklärung: In der definierten Tabelle befinden sich Ziffern. Was müsste ich tun, um möglichst effektiv und mit wenig code zum Beispiel an den Inhalt der Zelle 1b ranzukommen ??

vielen dank

gruß
Julian
BlackJack

@juju: Welche Informationen darf man denn dafür heranziehen? Muss man sich an den Werten an den Kopfzeilen und -spalten orientieren, oder darf man annehmen dass es die erste Tabelle auf der "Report"-Ebene ist und das Zelle 1b unabhängig von der Beschriftung in der zweiten Tabellenzeile die dritte Zelle ist? Dann ginge das mit `lxml` und einem XPath-Ausdruck zum Beispiel so:

Code: Alles auswählen

In [850]: from lxml import etree

In [851]: doc = etree.parse('test.xml')

In [852]: doc.xpath('/Report/Table[1]/Row[2]/Cell[3]/Data/text()')
Out[852]: ['640']
Falls '640' jetzt hier tatsächlich der gesuchte Wert war. Man kann auch Variablen im XPath-Ausdruck unterbringen und von Python aus Werte daran binden. Damit liesse sich der Ausdruck parametrisieren und in einer Funktion kapseln der man das Dokument, die Tabellen-, Zeilen-, und Zellennummer übergibt.

Aber musst Du da wirklich vereinzelte Werte rauspicken oder eher alle oder zumindest die Mehrzahl der Zelleninhalte verarbeiten? Dann würde ich eher eine Funktion schreiben, welche die Tabelle in eine Datenstruktur in Python umwandelt. Zum Beispiel eine "2D-Liste", also eine Liste die Listen mit den Zeilen enthält.

Dein erster Ansatz ist übrigens auch total fragil, weil Du Dich darauf verlässt, dass bestimmte Information an festen Zeilen und Spaltenwerten in der Textdatei stehen. Das wird von XML aber überhaupt nicht garantiert. Das könnte auch alles auf einer einzigen Zeile stehen und wäre höchstwahrscheinlich immer noch eine gültige Datei in diesem Format.

Ansonsten verstehe ich nicht so ganz wieso Du in `outputList` erst Verzeichnissnamen steckst (`root`) und die dann hinterher wieder mit einem Test ausschliesst!? Das Filtern nach XML-Dateien hätte ich übrigens schon beim Erstellen der Liste gemacht. Und ohne regulären Ausdruck. Man kann das mit rekursiv/nicht-rekursiv auch nur mit `os.walk()` erledigen, dann braucht man da nicht zwei verschiedene Wege um die Liste zu erstellen. Zum Verbinden von Dateipfaden gibt es `os.path.join()`. Das ist plattformunabhängig. Das liefe dann alles auf folgendes hinaus (ungetestet):

Code: Alles auswählen

recursive = True
xml_filenames = list()
for root, dummy, filenames in os.walk(sys.argv[1]):
    for filename in filenames:
        if filename[-4:].lower() == '.xml':
            xml_filenames.append(os.path.join(root, filename))
    if not recursive:
        break
Das ``os._exit(0)`` am Ende ist zum einen überflüssig -- der Programmfluss endet dort ja sowieso -- und zum anderen sind Namen, die mit einem Unterstrich beginnen Interna, die man nicht verwenden sollte wenn man nicht genau weiss was man da tut. Zum Beenden des Prozesses mit einem expliziten Exit-Code ist `sys.exit()` der offizielle Weg.
juju
User
Beiträge: 47
Registriert: Dienstag 25. Mai 2010, 16:02

@juju: Welche Informationen darf man denn dafür heranziehen? Muss man sich an den Werten an den Kopfzeilen und -spalten orientieren, oder darf man annehmen dass es die erste Tabelle auf der "Report"-Ebene ist und das Zelle 1b unabhängig von der Beschriftung in der zweiten Tabellenzeile die dritte Zelle ist?
-> kopfzeile ist zunächst "egal"... die xmldatei spannt folgende Tabelle auf:
a b c d
1
2
3
4

Nun sollen alle Werte aus Spalte "b" als integer in einer vier Listen abgespeichert werden (nr1b, nr2b, nr3b, nr4b). Das Programm soll darüber hinaus alle xml dateien eines (umfangreichen) Ordners einlesen und die Listen nr1b, nr2b ... mit den Zahlen auffüllen... Ziel ist dann eine Auswertung der Daten: Mittelwert und Standardabweichung...

Das Problem ist in der Tat, dass die XML-Datei nicht immer gleich aufgebaut sind...
juju
User
Beiträge: 47
Registriert: Dienstag 25. Mai 2010, 16:02

Code: Alles auswählen

recursive = True
xml_filenames = list()
for root, dummy, filenames in os.walk(sys.argv[1]):
    for filename in filenames:
        if filename[-4:].lower() == '.xml':
            xml_filenames.append(os.path.join(root, filename))
    if not recursive:
        break
Meldung: listindex out of range...
Zuletzt geändert von Anonymous am Mittwoch 26. Mai 2010, 10:01, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
BlackJack

Ich habe in der Beispieldatei die Datenzeile jetzt noch dreimal kopiert, dann geht das mit "Spalte b" also die dritte Spalte in der ersten Tabelle auf 'Report'-Ebene so:

Code: Alles auswählen

In [882]: doc.xpath('/Report/Table[1]/Row/Cell[3]/Data/text()')
Out[882]: ['640', '640', '640', '640']
Jetzt müsstest Du aber mal langsam anfangen Dich mit XPath auseinander zu setzen. Und wahrscheinlich auch mit Python-Grundlagen.

Das mit Namen durchnummerieren wurde doch schon mal angesprochen: Sollte man nicht machen. Da würde man eher eine Liste von Listen verwenden oder ein Dictionary das den Zeilenheader auf Listen mit den Werten abbildet.

Wenn die XML-Dateien nicht immer gleich aufgebaut sind, müsstest Du irgendwie formal beschreiben können was Du in allen suchst und dass dann in XPath und Python formulieren.

Bei dem `IndexError` sehe ich in dem Quelltext nur eine Stelle wo das passieren kann, und das ist die gleiche in der das bei Deinem auch der Fall ist. Schau Dir doch den Traceback noch einmal genau an und überlege.

Sollte es nicht daran liegen was ich gerade vermute, dann zeig doch mal bitte den genauen Traceback.
juju
User
Beiträge: 47
Registriert: Dienstag 25. Mai 2010, 16:02

wirklich vielen Dank für die Hilfe...

ich arbeite zur Zeit eigentlich ausschließlich mit dem Buch: Python von Peter Kaiser, Johannes Ernesti
(Das umfassende Handbuch - Aktuell zu Python 2.5 / 3.0)... das Problem ist, hier sind kaum Beispiele dargestellt...

könnt ihr mir vllt Tutorials oder andere Literatur empfehlen, um ein guten Überblick zu bekommen ??

gruß
Juju
Benutzeravatar
Windsurfer
User
Beiträge: 11
Registriert: Mittwoch 26. Mai 2010, 11:47

Um die Grundlagen von Python zu verstehen, kann ich das hier empfehlen.
Ich beschäftige mich seit 4 Wochen mit Python und das war ein super Einstieg:

http://abop-german.berlios.de/read/

Auch sehr Informativ sind diese Seite:
http://en.wikibooks.org/wiki/Python_Programming/
Lastalda
User
Beiträge: 10
Registriert: Dienstag 25. Mai 2010, 14:29

Für den Anfang, grade wenn man noch keine andere Programmiersprache kann, finde ich How to think like a computer scientist - Learning with Python sehr angenehm (und es steht als kostenloser Download zur Verfügung!). Geht zwar nicht extrem in die Tiefe was spezielle Funktionen und Module etc. angeht, aber es bildet erstmal ne gute Grundlage in Sachen Programmstruktur und "was mach ich hier eigentlich?", was ich an der Uni sehr vermisst hab. :)
BlackJack

Und das Tutorial in der Python-Dokumentation sollte man mal durchgearbeitet haben.

XML und verwandte Techniken wie XPath sind von Python unabhängige Themen, da solltest Du Dir am besten auch ein wenig Doku und/oder ein Tutorial zu suchen.
juju
User
Beiträge: 47
Registriert: Dienstag 25. Mai 2010, 16:02

@ blackjack: ist es ratsam die werte mit einer schleife inkl. xpath methode aus der xml-datei zu schreiben ?
->

Code: Alles auswählen

k=0
for i in range(2,6):
    for j in range(3,8,4):
        liste_irgendwas = doc.xpath('/Report/Table[1]/Row[i]/Cell[j]/Data/text()')
        k = k + 1
        print a
        print 'schleife: ', k
Für denn Fall die Datei hätte soviele Zeilen und Spalten, wie in der SChleife angegeben!
BlackJack

@juju: Wenn das gewünschte Ergebnis herauskommt wäre das ratsam, aber ich dachte Du wolltest Die Werte innerhalb des Programms noch weiterverarbeiten!?

Ausserdem könntest Du das doch auch einfach selbst ausprobieren. Bei dem Beispiel fallen mir drei Sachen auf: Entweder Dir ist nicht ganz klar was `range()` als Ergebnis liefert, oder Du hast die "`j`-Schleife" etwas undurchsichtig formuliert:

Code: Alles auswählen

In [905]: range(3, 8, 4)
Out[905]: [3, 7]
Falls das wirklich so gewollt ist, würde ich die Liste direkt hinschreiben, statt sie mit `range()` auszudrücken.

Das zweite sind die Variablen in dem XPath-Ausdruck. XPath ist eine eigene Sprache mit eigenen Regeln. Dort muss man für den Zugriff auf Variablen ein '$' vor den Namen schreiben. Und die Namen aus dem Python-Programm sind nicht automatisch bekannt, man muss die beim Aufruf explizit als Schlüsselwort-Argumente angeben.

Das dritte und letzte ist der `NameError`, der Dir bei `a` um die Ohren fliegen würde und das `liste_irgendwas` nicht verwendet wird. Du solltest bei solch kurzen Snippets ruhig etwas experimentieren bevor Du sie postest. Viele Fragen klären sich damit vielleicht von selbst.
juju
User
Beiträge: 47
Registriert: Dienstag 25. Mai 2010, 16:02

@ blackjack: Danke für die Erklärung... ja ich hätte damit experimentieren können, wenn ich das Original der XML Datei gehabt hätte ;) , da ich aber zur Zeit nicht zuHAuse bin, habe ich an einem anderen Rechner lediglich mit xpatch und der geposteten BeispielXML rumprobiert...

... nun bin ich wieder zu Hause... :) und bin wieder fleißig am basteln...
juju
User
Beiträge: 47
Registriert: Dienstag 25. Mai 2010, 16:02

Code: Alles auswählen

from lxml import etree
doc = etree.parse('test.xml')
for i in range(2,6):
    dict= {i : doc.xpath('/Report/Table[1]/Row[i]/Cell[3]/Data/text()')}
    print dict
wie kann ich es jetzt schaffen, dass xpath die Schleifenvariable i in Row durchzählt und die Werte ins dictonary schreibt? ... den Schlüsselwert nimmt er schonmal (gehört ja auch nicht zu xpath!) ... während des xpath-Befehls (also Row) funktioniert der Befehl mit '$i' nicht...

gruß
juju
User
Beiträge: 47
Registriert: Dienstag 25. Mai 2010, 16:02

hab gerade ein lösung gefunden, sogar ohne schleife...

Code: Alles auswählen

Offset = doc.xpath('/Report/Table[position()<3]/Row[position()]/Cell[3]/Data/text()')
Treshold = doc.xpath('/Report/Table[position()<3]/Row[position()]/Cell[7]/Data/text()')
print Offset, Treshold
BlackJack

@juju: Das `position()` bei `Row` ist überflüssig. Einfach nur `/Row/` reicht an der Stelle aus.
Antworten