Beispiel:
Code: Alles auswählen
>>> s = "äöü"
>>> s
'\xc3\xa4\xc3\xb6\xc3\xbc'
>>> x = s[3:]
>>> x
'\xb6\xc3\xbc'
>>>
PangoWarning: Invalid UTF-8 string passed to pango_layout_set_text()
Kann man einen Unicode-String zeichensicher zerschneiden?
Code: Alles auswählen
>>> s = "äöü"
>>> s
'\xc3\xa4\xc3\xb6\xc3\xbc'
>>> x = s[3:]
>>> x
'\xb6\xc3\xbc'
>>>
Du hast ja keinen Unicode, sondern einen Byte-Code-String!rhersel hat geschrieben: Kann man einen Unicode-String zeichensicher zerschneiden?
Code: Alles auswählen
s = u"äüö"
Nein, nicht ohne beträchtlichen Aufwand.rhersel hat geschrieben:Kann man einen Unicode-String zeichensicher zerschneiden?
Code: Alles auswählen
ucontent = unicode(mybytestring)
content = ucontent[:cut]
Code: Alles auswählen
s = b"a\xcc\x88".decode("utf-8")
print(len(s))
print(ord(s[1]))
Sag ich jasma hat geschrieben:Allgemein kann man sich auch in der Basic-Plane NICHT sicher sein, dass Python-Unicode-Strings schneidbar sind. Man schaue sich dieses Beispiel (unter Python 3.x) an:
Naja, sind ja auch zwei Zeichen. Das mit den 4-byte-Zeichen finde ich viel schlimmer, da wird einem wirklich ein Zeichen als zwei verkauft. Ich würde das durchaus als Bug bezeichnen.Der String ist ein einzelnes "ä", doch es wird in einer alternativen Kodierung bestehend aus "a" und Umlaut ("¨") zusammengesetzt. Das erkennt "len" aber nicht und liefert 2 statt 1.
In der Mitte ist der böse Teil zu sehen: Würfeleis.g38
asg50
(lp337
sg52
(lp338
S'Im Elektromixer mit viel Eis (zerstossenes oder W\xc3\xbcrfeleis) mixen und mit dem Eis in das Cocktailglas geben. Deko: frei'
p339
aS'2010.04.18, 18:09:40'
p340
ag65
asg72
Code: Alles auswählen
>>> a = "Im Elektromixer mit viel Eis (zerstossenes oder W\xc3\xbcrfeleis)"
>>> a
'Im Elektromixer mit viel Eis (zerstossenes oder W\xc3\xbcrfeleis)'
>>> b = a[:50]
>>> b
'Im Elektromixer mit viel Eis (zerstossenes oder W\xc3'
>>> print b
Im Elektromixer mit viel Eis (zerstossenes oder W
>>> c = unicode(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 49: ordinal not in range(128)
>>>
Das sollte doch ein Bug sein, oder?sma hat geschrieben:Allgemein kann man sich auch in der Basic-Plane NICHT sicher sein, dass Python-Unicode-Strings schneidbar sind. Man schaue sich dieses Beispiel (unter Python 3.x) an:Der String ist ein einzelnes "ä", doch es wird in einer alternativen Kodierung bestehend aus "a" und Umlaut ("¨") zusammengesetzt. Das erkennt "len" aber nicht und liefert 2 statt 1.Code: Alles auswählen
s = b"a\xcc\x88".decode("utf-8") print(len(s)) print(ord(s[1]))
Stefan
Nein, sind ja zwei verschiedene Zeichen/Codepoints. Ein wirklicher Bug ist nur, dass 4-byte-Zeichen(z.B. u'\U0001d11e') im Standard(UCS2)-Build von Python eine Länge von 2 haben. Da wird dann nämlich wirklich ein einzelner Codepoint auseinandergerupft.mkesper hat geschrieben:Das sollte doch ein Bug sein, oder?
Code: Alles auswählen
# python 3.x
import unicodedata
s = "a\u0308"
print(len(s))
print(len(unicodedata.normalize("NFC", s)))
s = "\u00e4"
print(len(s))
print(len(unicodedata.normalize("NFD", s)))
Laut Standard werden sie zumindest als "Characters" bezeichnet.sma hat geschrieben:Die "Combining Diacritical Marks" sind zwar Code Points, aber AFAIK keine Zeichen.
Erwischt man damit wirklich alles?Die Lösung ist, zu normalisieren, bevor man Strings zerlegt.
Das tue ich. Deswegen sind es Zeichen. Auch ASCII Nr. 7 ist ein Zeichen, es heißt in Unicode BELL. C-chars haben damit erstmal wirklich nichts zu tun. Aber das wird jetzt leicht OT.BlackJack hat geschrieben:@Darii: Da muss man wohl Typographie und Computer-Jargon auseinanderhalten. Bei Computern wird auch der Bytewert 7 in der ASCII-Kodierung als "character" bezeichnet. Aber klingeln oder piepsen ist für mich eher ein Ton als ein Zeichen.