Sicher dass keine Leerzeichen vor dem I auftauchen? Das ist bei mir nämlich passiert als ich den Code aus dem Forum kopiert habe. Sonst probier mal meine Variante. Die kann mit Leerzeichen am Anfang umgehen.python-fan hat geschrieben:(...) aber erzeugt keine Ausgabe und die Datei beinhaltet I.
Eine txt datei zeilenweise einlesen und vergleichen
-
- User
- Beiträge: 11
- Registriert: Donnerstag 4. Januar 2018, 14:38
snafu hat geschrieben:Ich würde wohl auch den Ansatz über groupby() gehen:Code: Alles auswählen
from itertools import groupby def parse(stream): sensor_id = value = None for line in stream: msg_type = line.split()[0].strip() if msg_type == 'I': sensor_id = line.split()[5].split('-')[0] if msg_type == 'A': value = line.split('"')[1].strip() if sensor_id and value: yield sensor_id, value sensor_id = value = None def cleanup(records): def get_id(record): return record[0] for sensor_id, sensor_data in groupby(records, get_id): last_data = list(sensor_data)[-1] yield last_data def print_records(stream): records = parse(stream) for sensor_id, value in cleanup(records): print('Sensor ID:', sensor_id) print('Value:', value) print() def main(): with open("deine_datei.txt") as stream: print_records(stream)
Hi irgendwie mache ich die ganze zeit etwas falsch, sobald ich es über Python Idle 2.7 ausführe habe ich keine Ausgabe, obwohl ich bei der with function den Dateinamen + r für lesen eingefügt habe. Sobald ich das Skript ausführe habe bekomme ich keine Ausgabe, was mache ich falsch?
-
- User
- Beiträge: 11
- Registriert: Donnerstag 4. Januar 2018, 14:38
ich wollte den obigen code testweise ausführen, um das Verhalten mir anzuschauen um dies als Lernansatz zu nehmen, ich habe lediglich nur den Dateinamen hinzugefügt.
-
- User
- Beiträge: 11
- Registriert: Donnerstag 4. Januar 2018, 14:38
Oh tut mir leid, ich habe vergessen die Funktion main aufzurufen, sorry Leute
d.h. ich habe jetzt print main() hinzugefügt. D.h. die anderen funktionen sind mit sich verbunden und müssen nicht explizit aufgerufen werden , oder täusche ich mich?
d.h. ich habe jetzt print main() hinzugefügt. D.h. die anderen funktionen sind mit sich verbunden und müssen nicht explizit aufgerufen werden , oder täusche ich mich?
Die main()-Funktion ist mehr zu Demozwecken gedacht. Du kannst in dein Programm natürlich direkt den Code aus main() rüberkopieren. Das Aufrufen der Hilfsfunktionen geschieht in print_records(). Deine (Python-)Programierkenntnisse scheinen sich ja in sehr überschaubaren Grenzen zu halten...python-fan hat geschrieben:d.h. ich habe jetzt print main() hinzugefügt. D.h. die anderen funktionen sind mit sich verbunden und müssen nicht explizit aufgerufen werden , oder täusche ich mich?
-
- User
- Beiträge: 11
- Registriert: Donnerstag 4. Januar 2018, 14:38
Ok danke vielmals für die Erklärung. Wenn man in einer anderen Programmiersprache programmiert und eine anderen Syntax gewohnt ist, kann man auch gewisse Sachen übersehen oder man braucht etwas, um es zu verstehen.
Hier mal mit Index-Operationen, um die "Wegwerf-Listen" zu vermeiden:
Code: Alles auswählen
from __future__ import print_function
from itertools import groupby
def parse(stream):
sensor_id = value = None
for line in stream:
msg_type = line.lstrip()[0]
if msg_type == 'I':
start = line.index('from') + 5
stop = line.index('-', start)
sensor_id = line[start:stop]
if msg_type == 'A':
start = line.index('"') + 1
stop = line.index('"', start)
raw = line[start:stop]
parts = raw.split(',')
value = tuple(map(int, parts))
if sensor_id and value:
yield sensor_id, value
sensor_id = value = None
def cleanup(records):
def get_id(record):
return record[0]
for sensor_id, sensor_data in groupby(records, get_id):
for record in sensor_data:
pass
yield record
def print_records(stream):
records = parse(stream)
for sensor_id, value in cleanup(records):
print('Sensor ID:', sensor_id)
print('Value:', value)
print()
def main():
with open("deine_datei.csv") as stream:
print_records(stream)
Das ist schon klar. Aber Funktionen und ihr Sinn, welcher sich normalerweise aus ihrem Namen ergibt, sind dir doch wohl bekannt.python-fan hat geschrieben:Wenn man in einer anderen Programmiersprache programmiert und eine anderen Syntax gewohnt ist, kann man auch gewisse Sachen übersehen oder man braucht etwas, um es zu verstehen.
Wenn du an bestimmten Stellen nicht weiterkommst, dann frag ruhig. Die groupby()-Doku hatte ich ja bereits verlinkt. Kannst bei Bedarf aber gerne eine Erklärung dazu auf Deutsch haben. Das tuple-map-Konstrukt, welches ich zum Parsen des Wertes nachträglich editiert hatte, könnte auch nicht jedem geläufig sein...
Du bist ja sehr konstruktiv mit deiner Kritik...Sirius3 hat geschrieben:Nicht Dein Ernst!snafu hat geschrieben:Hier mal mit Index-Operationen, um die "Wegwerf-Listen" zu vermeiden:
Weiß nicht wo das Problem liegt ob ich jetzt an Anführungszeichen splitte und das zweite Element rausfriemel oder ob ich mir die Start- und Endpunkte mittels index() hole. Ein Gefrickel ist es so oder so. Wirklich robuster ist das Splitten auch nicht. Man muss in beiden Fällen hoffen, dass sich das Format nicht ändert.
Bei der groupby-Variante missfällt mir, dass von den zurückgegebenen Iteratoren jeweils nur das letzte Element gebraucht wird. Bei nur einem oder zwei Elementen ist das unerheblich, aber bei vielen Einträgen wird dies unschön. In der Hinsicht finde ich die Filter-Lösung besser, die lediglich den zuletzt gelesenen Eintrag chached.
Um den Filter nicht in der Parser-Funktion zu haben, wäre auch ein Dekorator eine mögliche Lösung. Zur Abwechslung hier mal eine klassenbasierte Version (Python 3):
Um den Filter nicht in der Parser-Funktion zu haben, wäre auch ein Dekorator eine mögliche Lösung. Zur Abwechslung hier mal eine klassenbasierte Version (Python 3):
Code: Alles auswählen
class FilterDoubles:
def __init__(self, func):
self.func = func
def __call__(self, fobj):
id = data = None
for next_id, next_data in self.func(fobj):
if id and id != next_id:
yield id, data
id, data = next_id, next_data
yield id, data
@FilterDoubles
def get_sensor_data(fobj):
for line in filter(lambda line: line.startswith('I'), fobj):
parts = line.split()
sensor_id = parts[5][:-1]
data = ''.join(chr(int(c, 16)) for c in parts[-1].split('-') if c != '00')
yield sensor_id, data
with open(inputfile) as fobj:
for id, data in get_sensor_data(fobj):
print(id, data)
Für die Umwandlung der hexadezimalen Zeichen bringt Python übrigens schon selbst was mit:
Code: Alles auswählen
from binascii import unhexlify
# ...
hexstr = line.split()[-1].replace('-', '')
unhexlify(hexstr).strip(b'\00')
@Sirius3: Habe nochmal in die Doku geschaut und groupby scheint tatsächlich nichts zu cachen, sowie bei dieser Anwendung dem Dekorator ziemlich zu ähneln; der gefällt mir dennoch gut und manchmal kann es eben doch NIH sein ...
-
- User
- Beiträge: 11
- Registriert: Donnerstag 4. Januar 2018, 14:38
snafu hat geschrieben:Das ist schon klar. Aber Funktionen und ihr Sinn, welcher sich normalerweise aus ihrem Namen ergibt, sind dir doch wohl bekannt.python-fan hat geschrieben:Wenn man in einer anderen Programmiersprache programmiert und eine anderen Syntax gewohnt ist, kann man auch gewisse Sachen übersehen oder man braucht etwas, um es zu verstehen.
Wenn du an bestimmten Stellen nicht weiterkommst, dann frag ruhig. Die groupby()-Doku hatte ich ja bereits verlinkt. Kannst bei Bedarf aber gerne eine Erklärung dazu auf Deutsch haben. Das tuple-map-Konstrukt, welches ich zum Parsen des Wertes nachträglich editiert hatte, könnte auch nicht jedem geläufig sein...
Code: Alles auswählen
if msg_type == 'I':
start = line.index('from') + 5
stop = line.index('-', start)
sensor_id = line[start:stop]
if msg_type == 'A':
start = line.index('"') + 1
stop = line.index('"', start)
raw = line[start:stop]
parts = raw.split(',')
value = tuple(map(int, parts))
Vielen Dank auch an alle anderen, ich lerne viel neues dazu hier.
@python-fan: deshalb mag ich die Lösung mit »index« nicht, weil sie völlig unverständlich ist. Das erste Index sucht das Wörtchen 'from', also die Position des ›f‹, da muß man noch die 4 Zeichen und das Leerzeichen, also 5 weiter um an der Position der ›6‹ zu landen.