Anfänger - Problem mit Kodierung: UnicodeDecodeError
Verfasst: Samstag 28. Dezember 2013, 21:03
Hallo,
ich beschäftige mich seit quasi gestern Abend mit Python [...].
Ich arbeite seit einigen Wochen an batteriebetriebenen Funk-Temperatursensoren auf ATTiny84-Basis, die ihre Daten an einen zentralen Arduino per 433 Mhz funken.
Bisher war das ein kleiner Arduino Ethernet, der die Daten direkt an ein PHP-Webscript übergeben hat - da ich aber dadurch "Kabelgebunden" bin (da gibts kein WLan...), wollte ich mich mal versuchen einen einfachen Arduino an einen Raspberry Pi zu klemmen: Der läuft mit einem WLan-Stick und frisst die Arduino-Daten per COM.
Okay, soviel dazu: Mein Arduino spuckt die Daten am Raspberry Pi aus. Ich habe es auch geschafft, per python3-serial die Daten auszulesen, und per urllib.request an mein Webscript zu übergeben (GET).
Nachfolgend mal der Code:
Okay, mein Problem ist nun folgendes: Anscheinend gibt der Arduino den Datenstring (gleich vorformatiert, kommt so an: s=3&t=1990&h=6810&v=4615) Zeichen für Zeichen aus und hängt ein \n o.ä. an.
Manchmal macht das - aus welchem Grund auch immer - Probleme, den manchmal kommt beim Raspberry nicht der komplette Datenstring an, sondern nur ein Teil - oder ein kauderwelsch aus zwei Datenstrings, Beispiel: s=1s=3&t=1990&h=6840&v=4615.
Der Part "s=1" gehört zum vorherigen Datenpaket - allerdings fängt das damit an; wo der Rest dessen geblieben ist, weiß ich nicht.
Kurzum: Kommt nicht alles an, spuckt er mir folgende Meldung aus:
Starte ich das Script und es wirft nicht gleich diesen Fehler, läuft es Stundenlang ohne Fehler durch. Vermutlich passiert der Fehler, wenn ich das Script starte während der Arduino gerade Daten an den Raspberry übergibt. Dann kommt nur die Hälfte an...
Was ich aber nicht verstehe: Die Daten die von der seriellen Schnittstelle gelesen werden MÜSSEN doch ASCII sein; schließlich klappts ja - wenn der Fehler nicht gleich auftaucht - ohne Probleme.
Wie kann ich soetwas abfangen oder verhindern? Später soll das Script als Daemon oder per Cronjob täglich gestartet werden - wenn's einmal aussteigt, kriege ich das vermutlich nicht mit, und mir fehlen dann (im schlimmsten Fall) einen ganzen Tag Messwerte.
*Update*
Ich habe mal von ASCII auf UTF-8 umgeschwenkt; wenn ich mich richtig erinnere, sind alle Standard-Strings in Python 3 UTF-8 kodiert - kann also nicht schaden.
Anscheinend passiert obiger Fehler auch vereinzelt bei der Antwort der WebRequest:
Ich glaube, ich mache da einen grundlegenden Fehler :/
ich beschäftige mich seit quasi gestern Abend mit Python [...].
Ich arbeite seit einigen Wochen an batteriebetriebenen Funk-Temperatursensoren auf ATTiny84-Basis, die ihre Daten an einen zentralen Arduino per 433 Mhz funken.
Bisher war das ein kleiner Arduino Ethernet, der die Daten direkt an ein PHP-Webscript übergeben hat - da ich aber dadurch "Kabelgebunden" bin (da gibts kein WLan...), wollte ich mich mal versuchen einen einfachen Arduino an einen Raspberry Pi zu klemmen: Der läuft mit einem WLan-Stick und frisst die Arduino-Daten per COM.
Okay, soviel dazu: Mein Arduino spuckt die Daten am Raspberry Pi aus. Ich habe es auch geschafft, per python3-serial die Daten auszulesen, und per urllib.request an mein Webscript zu übergeben (GET).
Nachfolgend mal der Code:
Code: Alles auswählen
# Benötigt: python3-serial
import serial
import urllib.request
import sys
import datetime
#sys.stdout = open('/dev/null', 'w')
#sys.stdout = open('/var/log/serialread.log', 'w')
ser = serial.Serial('/dev/ttyACM0', 9600)
while 1:
time = datetime.datetime.now()
rs232 = ser.readline().decode("ascii")
print("Uhrzeit: ", time, end="\n")
print("Empfangene Daten: ", rs232, end="\n")
url = 'http://www.xxx.de/attiny/parse.php?r=1&key=xxxxx&' + rs232 #.decode("ascii")
urlrequest = urllib.request.urlopen(url).read()
urlrequest = urlrequest.decode("ascii")
print("URL: ", url, end="\n")
print("Ergebnis: ", urlrequest, end="\n")
print("--------", end="\n")
Manchmal macht das - aus welchem Grund auch immer - Probleme, den manchmal kommt beim Raspberry nicht der komplette Datenstring an, sondern nur ein Teil - oder ein kauderwelsch aus zwei Datenstrings, Beispiel: s=1s=3&t=1990&h=6840&v=4615.
Der Part "s=1" gehört zum vorherigen Datenpaket - allerdings fängt das damit an; wo der Rest dessen geblieben ist, weiß ich nicht.
Kurzum: Kommt nicht alles an, spuckt er mir folgende Meldung aus:
Code: Alles auswählen
pi@raspi01 ~/serialread $ python3 serialread.py
Uhrzeit: 2013-12-28 20:51:16.024846
Empfangene Daten: ss=3&t=1979&h=6830&v=4635
Traceback (most recent call last):
File "serialread.py", line 21, in <module>
urlrequest = urlrequest.decode("ascii")
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 226: ordinal not in range(128)
Was ich aber nicht verstehe: Die Daten die von der seriellen Schnittstelle gelesen werden MÜSSEN doch ASCII sein; schließlich klappts ja - wenn der Fehler nicht gleich auftaucht - ohne Probleme.
Wie kann ich soetwas abfangen oder verhindern? Später soll das Script als Daemon oder per Cronjob täglich gestartet werden - wenn's einmal aussteigt, kriege ich das vermutlich nicht mit, und mir fehlen dann (im schlimmsten Fall) einen ganzen Tag Messwerte.
*Update*
Ich habe mal von ASCII auf UTF-8 umgeschwenkt; wenn ich mich richtig erinnere, sind alle Standard-Strings in Python 3 UTF-8 kodiert - kann also nicht schaden.
Anscheinend passiert obiger Fehler auch vereinzelt bei der Antwort der WebRequest:
Code: Alles auswählen
Traceback (most recent call last):
File "serialread.py", line 23, in <module>
urlrequest = urllib.request.urlopen(url).read().decode("utf-8") # Web-Parse-Request absetzen und Statusausgabe in UTF-8 konvertieren
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe4 in position 226: invalid continuation byte