Parsing Hilfe...

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.
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

Hi

Ich frage mich ob man statt dieser ListComprehension es mit ner While Schleife vereinfachen könnte...

Also in Perl würde ich folgendes schreiben

Code: Alles auswählen

$table{$1} = [ split /,/,$2 ]  while ( $config =~ /(\w+)\s*\[(.*?)\]/g );
aber mir ist nicht klar wie ich das in Python so (dh. mit while über matches iterieren) abbilden könnte...

Grüße
rolf

EDIT: typo korrigiert
Ronnie
User
Beiträge: 73
Registriert: Sonntag 21. März 2004, 17:44

Hallo Rolf,

wieso willst du unbedingt eine while-Schleife verwenden, wenn sich doch ein for-in-Loop eher anbieten würde? Um die Frage aus deiner Mail zu beantworten, wenn du von der Regex einen Iterator möchtest, bietet sich re.finditer an.

Gruß,
Ronnie
Achtung: User ist ein Python-Lehrling!
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

Hi Ronnie
Ronnie hat geschrieben: wieso willst du unbedingt eine while-Schleife verwenden, wenn sich doch ein for-in-Loop eher anbieten würde?
eine while schleife kann ich abbrechen wenn ich gefunden habe was ich suche, nach meinem Verständnis produziert for-in ja erst eine liste aller matches bevor durchsucht wird.

Bei einem langen configfile kann das unnötig lange dauern...

Oder sehe ich da etwas falsch, erzwingen die runden Klammern um die Comprehension dass auch alle Unterausdrücke nur noch lazy evaluiert werden?

bye
rolf
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

LanX hat geschrieben:eine while schleife kann ich abbrechen wenn ich gefunden habe was ich suche, nach meinem Verständnis produziert for-in ja erst eine liste aller matches bevor durchsucht wird.
Auch eine For-Schleife kann mit break abgebrochen werden. Weder for noch while produzieren eine Liste, "durchsucht" wird auch nichts (wonach sollte auch gesucht werden? und was?).
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

derdon hat geschrieben:Auch eine For-Schleife kann mit break abgebrochen werden. Weder for noch while produzieren eine Liste, "durchsucht" wird auch nichts (wonach sollte auch gesucht werden? und was?).
in anderen Worten ist sowas ein lazy iterator den ich billig abbrechen kann wenn m meinen Kriterien entspricht...

Code: Alles auswählen

 for m in re.findall(r'(\w+)\s*\[(.+)\]', config)
... oder werden erst allle Fundstellen der RegEx zwischengespeichert bevor for-in drüberläuft?

EDIT: Wohlgemerkt wenn runde Klammern drumrumstehen die eine Comprehension in einen Iterator verwandeln.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

finditer wurde doch schon erwähnt. findall erzeugt eine Liste.
MfG
HWK
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

HWK hat geschrieben:finditer wurde doch schon erwähnt. findall erzeugt eine Liste.
MfG
HWK
Dachte ich mir, ich habe jetzt auch nur die Nachfragen von derdon und Ronnie beantwortet.

Anyway meine Frage bzgl der Iteratorform einer ListComprehension bleibt offen.

Wird die Lazyness auf alle Ebenen durchgeschleift inkl. re.findall ?

Eher nicht, oder?

MfG
rolf
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

LanX hat geschrieben: aber mir ist nicht klar wie ich das in Python so (dh. mit while über matches iterieren) abbilden könnte...
verstehe ich die Anwendung von re.finditer richtig dass ich den Iterator unmittelbar vorher erst einer temporären Variablen zuordnen muss, die ich dann mit while iteriere?

Oder gibt es einen syntaktischen Trick die Variable zu überspringen und die Iteratordefinition in der While-Bedingung stattfinden zu lassen, (wie in dem Beispiel in einer anderen Sprache deren Namen ich lieber nicht nochmal ausspreche ;)?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

[pseudopython]
for x in finditer:
if found: break[/pseudopython]

Du willst kein `while`. Und syntaktische, magische Tricks gibt es in Python gluecklicherweise auch nicht ;)
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

Danke cofi! :)

Mittlerweile bin ich auch selbst darauf gekommen das for-in immer ein iterierbares Objekt frisst, und eine Liste einfach nur ein weiteres dieser Objekte ist ...
(nettes Design :!:)


Aber was geht jetzt hier schief, wieso klappts mit findall aber nicht mit finditer?

Code: Alles auswählen

>>> for m in re.findall(r'(\w+)\s*\[(.+)\]', config): 
...  table[m[0]]=m[1].split(",")
... 
>>> table
{'COUNT': ['1'], 'LOOPSTART': ['TEST_FLASHMODE'], 'TARGET': ['10'], 'DIAG': ['SET_ENERGIESPARMODE_NORMAL'], 'SEND': ['31', '01', '0F', '0C', '00'], 'SOURCE': ['F1'], 'EXPECT': ['71', '01', '0F', '0C', '*'], 'TIMEOUT': ['0']}
>>> table={}
>>> for m in re.finditer(r'(\w+)\s*\[(.+)\]', config): 
...  table[m[0]]=m[1].split(",")
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
TypeError: '_sre.SRE_Match' object is unsubscriptable
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

nach einigem googlen bin ich auf die Methode "group()" gestoßen, so läufts

Code: Alles auswählen

>>> table={}
>>> for m in re.finditer(r'(\w+)\s*\[(.+)\]', config): 
...  table[m.group(1)] = m.group(2).split(',')
... 
>>> table
{'COUNT': ['1'], 'LOOPSTART': ['TEST_FLASHMODE'], 'TARGET': ['10'], 'DIAG': ['SET_ENERGIESPARMODE_NORMAL'], 'SEND': ['31', '01', '0F', '0C', '00'], 'SOURCE': ['F1'], 'EXPECT': ['71', '01', '0F', '0C', '*'], 'TIMEOUT': ['0']}
allerdings was ich über nettes Design gesagt habe nehm ich zurück ... :(

Warum finditer hier ein Objekt mit ganz anderem Interface zurückgibt als findall, insbesondere ein nicht indizierbares fällt mir schwer zu verstehen...
walha2006
User
Beiträge: 15
Registriert: Sonntag 7. Februar 2010, 21:24

ich wollte eingitlich Text-Dateien, wie unten angegeben, öffnen und so parsen:
1.Python liest diese LOOPSTART und nimmt dem Wert von COUNT[..]
2.er muss die Ausgaben bis LOOPENDE wiederholen (ZB hier 5 mal)
3.in jede Zeile steht
DIAG[] SEND[] EXPECT[] TIMEOUT [] SOURCE[] TARGET []
nur zwichen den klammen ändert sich

kann ich in Python Blöcke (Strukturen) machen ?
ZB. ein Struktur mit Elements (DIAG,SEND,TIMEOUT,SOURCE,TARGET)
und eine Zweite mit diesem Elements(LOOPSTART, COUNT,LOOPENDE)
????????????????


LOOPSTART [TEST] COUNT [5]
DIAG [T] SEND[22,3F]EXPECT[] TIMEOUT [0] SOURCE[F1] TARGET [00]

DIAG [T] SEND[22,0B]EXPECT[] TIMEOUT [0] SOURCE[F1] TARGET [05]

DIAG [T] SEND[22,3F]EXPECT[] TIMEOUT [0] SOURCE[F1] TARGET [0D]


WAIT [5000]
LOOPEND [TEST]
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

a) ja es geht
b) die bisher geposteten Lösungen mit einem hash/dictionary solltest du vergessen, weil sie unsortiert sind, es aber bei dir auf die Reihenfolge ankommt.

nimm eine der gezeigten for-in schleifen, merke dir den "counter" wenn dein "loopstart" beginnt und werte ihn dach belieben aus wenn "loopend" kommt.

ListComprehensions solltest du IMHO jetzt besser lassen, Ronnie will nur spielen. ;-)
Ronnie
User
Beiträge: 73
Registriert: Sonntag 21. März 2004, 17:44

LanX hat geschrieben:(...) die bisher geposteten Lösungen mit einem hash/dictionary solltest du vergessen (...)
Sorry, der OP (walha2006) hat in seinem ersten Post die Problemstellung anders beschrieben - bzw. nicht die Mühe gemacht sein Problem richtig zu beschreiben. Das fällt also in die Kategorie: "Ich wollte einen Lamborghini, konnte es aber nicht aussprechen." :roll:
Achtung: User ist ein Python-Lehrling!
walha2006
User
Beiträge: 15
Registriert: Sonntag 7. Februar 2010, 21:24

Ronnie hat geschrieben:
LanX hat geschrieben:(...) die bisher geposteten Lösungen mit einem hash/dictionary solltest du vergessen (...)
Sorry, der OP (walha2006) hat in seinem ersten Post die Problemstellung anders beschrieben - bzw. nicht die Mühe gemacht sein Problem richtig zu beschreiben. Das fällt also in die Kategorie: "Ich wollte einen Lamborghini, konnte es aber nicht aussprechen." :roll:
ja ,sorry ,ich habe mein Problem nicht gut beschrieben , aber jetzt ,ich glaube ,es ist schön klar ....und vielen danke Ronnie ,dein Antwort hat mir gut geholfen ,aber danach habe ich fesgestellt ,das Problem mit dem Loop ...geht einfach nicht mit dem hash/dictionary.. :roll:
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

Ronnie hat geschrieben:Sorry, ...
@Ronnie: schon klar....
Zuletzt geändert von LanX am Sonntag 21. Februar 2010, 22:57, insgesamt 1-mal geändert.
Ronnie
User
Beiträge: 73
Registriert: Sonntag 21. März 2004, 17:44

walha2006 hat geschrieben:... das Problem mit dem Loop ...geht einfach nicht mit dem hash/dictionary.. :roll:
Dann eben mit einem Array_of_Dictionaries:

Code: Alles auswählen

>>> config = """LOOPSTART [TEST] COUNT [5]
DIAG [T] SEND[22,3F]EXPECT[] TIMEOUT [0] SOURCE[F1] TARGET [00]
DIAG [T] SEND[22,0B]EXPECT[] TIMEOUT [0] SOURCE[F1] TARGET [05]
DIAG [T] SEND[22,3F]EXPECT[] TIMEOUT [0] SOURCE[F1] TARGET [0D]
WAIT [5000]
LOOPEND [TEST]"""
>>> table = [dict([ (m[0], m[-1].split(',')) if re.match(r'[0-9A-F*]+,', m[-1]) else m  for m in re.findall(r'(\w+)\s*\[(.*?)\]', l)]) for l in config.split("\n")]
Achtung: User ist ein Python-Lehrling!
walha2006
User
Beiträge: 15
Registriert: Sonntag 7. Februar 2010, 21:24

Ronnie hat geschrieben:
walha2006 hat geschrieben:... das Problem mit dem Loop ...geht einfach nicht mit dem hash/dictionary.. :roll:
Dann eben mit einem Array_of_Dictionaries:

Code: Alles auswählen

>>> config = """LOOPSTART [TEST] COUNT [5]
DIAG [T] SEND[22,3F]EXPECT[] TIMEOUT [0] SOURCE[F1] TARGET [00]
DIAG [T] SEND[22,0B]EXPECT[] TIMEOUT [0] SOURCE[F1] TARGET [05]
DIAG [T] SEND[22,3F]EXPECT[] TIMEOUT [0] SOURCE[F1] TARGET [0D]
WAIT [5000]
LOOPEND [TEST]"""
>>> table = [dict([ (m[0], m[-1].split(',')) if re.match(r'[0-9A-F*]+,', m[-1]) else m  for m in re.findall(r'(\w+)\s*\[(.*?)\]', l)]) for l in config.split("\n")]
aber Dem Inhalt von dem Datein ändert sich ,Besonders zwischen [ ] ,ändert sich ,wie kann ich die Werte markieren Z.B im COUNT[?]?
:roll:
Ronnie
User
Beiträge: 73
Registriert: Sonntag 21. März 2004, 17:44

walha2006 hat geschrieben:aber Dem Inhalt von dem Datein ändert sich ,Besonders zwischen [ ] ,ändert sich ,wie kann ich die Werte markieren Z.B im COUNT[?]? :roll:

Code: Alles auswählen

table[0]['COUNT']
Zugriff über die entstandene Datenstruktur?!
Achtung: User ist ein Python-Lehrling!
Ronnie
User
Beiträge: 73
Registriert: Sonntag 21. März 2004, 17:44

da ich vermute, dass der OP Probleme hat die verschachtelte Datenstruktur zu nutzen, hier mal ein kleines (konstruiertes) Beispiel:

Code: Alles auswählen

>>> config = """LOOPSTART [TEST] COUNT [5]
DIAG [T] SEND[22,3F]EXPECT[] TIMEOUT [0] SOURCE[F1] TARGET [00]
DIAG [T] SEND[22,0B]EXPECT[] TIMEOUT [0] SOURCE[F1] TARGET [05]
DIAG [T] SEND[22,3F]EXPECT[] TIMEOUT [0] SOURCE[F1] TARGET [0D]
WAIT [5000]
LOOPEND [TEST]"""
>>> table = [dict([ (m[0], m[-1].split(',')) if re.match(r'[0-9A-F*]+,', m[-1]) else m  for m in re.findall(r'(\w+)\s*\[(.*?)\]', l)]) for l in config.split("\n")]
>>> class ComProbe:
	def __init__(self, t):
		self.name = t[0]['LOOPSTART']
		self.cnt = t[0]['COUNT']
		self.tests = t[1:-1]
	def run(self):
		for i in range(0, int(self.cnt)):
			print("running " + self.name + " for " + str(i+1) + " time:")
			for test in self.tests:
				if 'DIAG' in test:
					print("\tsending " + str(test['SEND']) + " from " + test['SOURCE'] + " to " + test['TARGET'] )
				else:
					print("\twaiting: "+ test['WAIT'])

					
>>> t = ComProbe(table)
>>> t.run()
Achtung: User ist ein Python-Lehrling!
Antworten