smstools und Umlaute unter python

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
haidi
User
Beiträge: 20
Registriert: Montag 28. Dezember 2015, 23:03

Ich verarbeite unter Python und Raspian SMS über smstools.

Beim zeilenweisen Einlesen der von SMS-Tools bereit gestellten Datei mit dem Befehl

Code: Alles auswählen

i=1
for line in datei
	text=line.rstrip()
stürzt das Programm, wenn in der Datei Umlaute sind, ab.
Fehlermeldung:
UnicodeDecodeError 'utf-8'codec can't decode byte 0xf6 in position 221

File "/usr/lib/python3.4/codecs.py", line 313, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf6 in position 221: invalid start byte
byte 0xf6 ist das "ö"

Sprache ist auf Deutsch utf-8 einstellt.

Was kann ich da tun?
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@haidi: die Datei, die Du einliest, ist offensichtlich nicht UTF-8 kodiert, sondern in einer anderen Kodierung, die Du beim Öffnen der Datei explizit angeben mußt.
haidi
User
Beiträge: 20
Registriert: Montag 28. Dezember 2015, 23:03

Danke, das wärs ja eigentlich, wenn nicht...

im Terminal mit file Dateiname den Typ bestimmt, antwort:
news or mail, ISO-8859 text

DAnn die Datei geöffnet mit:

HAdatei=open(dateiname,encoding='ISO-8859")

Fehlermeldung:
Lookup error: unknown encoding ISO-8859

Nach ein bisschen googlen die Lösung gefunden:
Wenn diese Fehlermeldung bei ISO-8859 kommt, dann mit cp1252 probieren - voila, es hat geklappt.
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@haidi: das Encoding per "file" zu bestimmen, ist mehr oder weniger glückliches Raten. Es wäre besser, Du wüßtest, mit welchem Encoding Du die Datei erstellt hast.
haidi
User
Beiträge: 20
Registriert: Montag 28. Dezember 2015, 23:03

Die Datei hab ich nicht selbst erstellt, es ist eine SMS die von SMSTools erstellt wurde.
Auf Grund deines Postings habe ich jetzt noch einmal gegoogelt und diesen Hinweis gefunden:

Code: Alles auswählen

It is not possible to send using UTF-8 alphabet. Internal alphabet of smstools is ISO-8859-15. This means that if whole message can be shown using ISO alphabet, it can be sent using GSM alphabet which is 7-bit character set. If some character is outside of ISO-8859-15 alphabet, whole message is converted to UCS2, which means 16-bit Unicode character set. With UCS2 all chinese characters can be shown.
Inhalt so einer SMS-Datei:

Code: Alles auswählen

From: 431234567890
From_TOA: 91 international, ISDN/telephone
From_SMSC: 436640501
Sent: 16-01-11 09:27:54
Received: 16-01-11 09:28:11
Subject: GSM1
Modem: GSM1
IMSI: 232128220592945
Report: no
Alphabet: ISO
Length: 8

Blödsinn
die letzte Zeile ist der Inhalt der Datei - hab ich mir schicken lassen, damit ich die Behandlung einer SMS von einer nicht zugelassenen Telefonnummer testen kann und dabei bin ich dann auf das Problem mit den Umlauten gestoßen.

Jedenfalls funktioniert auch ISO-8859-15, wie ich festgestellt habe.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Es steht doch schon in der SMS-Datei welches Encoding drin ist: `Alphabet: ISO` (Ich nehme mal an, wenn das nicht ISO ist, dann ist es UCS2). Also Header lesen und den Rest (den Inhalt) dementsprechend behandeln.

Sowas in der Art:

Code: Alles auswählen

In [6]: with open('file.sms, 'rb') as f:
   ...:     t = f.read()
   ...:     

In [7]: # encoding = header['Alphabet'] == 'ISO' ? 'cp1252' : 'UCS-2'

In [8]: t.decode(encoding)
Out[8]: 'ö\n'

In [9]: t
Out[9]: b'\xc3\xb6\n'
the more they change the more they stay the same
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Nur wuerde ich tatsaechlich Python schreiben, statt C Ternaries:

Code: Alles auswählen

encoding = 'cp1252' if header['Alphabet'] == 'ISO' else 'UCS-2'
Wobei ich 'cp1252' fuer falsch halte, da das Zitat explizit von ISO-8859-15 spricht und nicht von Windows Codepages.
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@cofi: ISO-8859-15 ist eine Untermenge von cp1252, da macht mal beim decodieren mal nichts falsch.
@haidi: das korrekte Vorgehen ist wie bei HTTP, den Header als ASCII bis zur ersten Leerzeile zu lesen und zu parsen und den Rest entsprechend dem "Alphabet" zu dekodieren.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

cofi hat geschrieben:Nur wuerde ich tatsaechlich Python schreiben, statt C Ternaries:

Code: Alles auswählen

encoding = 'cp1252' if header['Alphabet'] == 'ISO' else 'UCS-2'
Oops :oops:
the more they change the more they stay the same
haidi
User
Beiträge: 20
Registriert: Montag 28. Dezember 2015, 23:03

Danke für die vielen Antworten - nun ist mir etliches klarer.

Schon 15 Jahre her, dass ich mich mit Programmieren beschäftigt habe, damals noch Clipper (dbase-Compiler), lief auf DOS-Ebene und da hatte ich nur mit ASCII-Code zu tun.
Antworten