Fragen zu Zeichensätzen

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.
Antworten
Benutzeravatar
Dr.Miles
User
Beiträge: 38
Registriert: Montag 15. Dezember 2008, 08:33
Wohnort: Mannheim
Kontaktdaten:

Hallo, lese mir gerade diesen Beitrag durch und habe ein paar Fragen:

1. Wenn eine Datei UTF-8 ist und ich gebe 8895-1 als Zeichensatz an, dann wird das UTF-8 als 8895-1 interpretiert, richtig?
2. Wenn ich kein Encoding angebe, interpretiert Python die File standartmäßig als Unicode?
3. Unicode ist einfach eine Tabelle mit allen möglichen Zeichen und UTF-8 eine Möglichkeit diese digital zu speichern? (Da kann irgendwas nicht stimmen, aber das schlussfolgere ich wenn ich bei Wikipedia lese:
UTF-8 (Abk. für 8-bit Unicode Transformation Format) ist die am weitesten verbreitete Kodierung für Unicode-Zeichen.
)
4. Ich habe gelesen 1 Zeichen braucht 1Byte, aber nur wenn man es in ASCII kodiert, oder? Bei UTF-8 nur wenn das Zeichen im ASCII-Code vorkommt, richtig? (also sich als 1 Byte darstellen lässt (also <128))
5. Warum wird folgende Exception geworfen
SyntaxError: Non-ASCII character
wenn ich ohne ein Encoding anzugeben die Datei
mit Sonderzeichen ausführen möchte? Was hat das mit ASCII zu tuen? Ich dachte Python nimmt standartmäßig alles Unicode?

Danke für die Antwort im voraus
Dr.Miles[/quote]
www.i2p2.de <--- sehr interressantes Anonymisierungsprojekt.
www.schaeuble-wegtreten.de <--- Petition gegen Schäuble
lunar

Dr.Miles hat geschrieben:1. Wenn eine Datei UTF-8 ist und ich gebe 8895-1 als Zeichensatz an, dann wird das UTF-8 als 8895-1 interpretiert, richtig?
Ja.
2. Wenn ich kein Encoding angebe, interpretiert Python die File standartmäßig als Unicode?
Python 3 versucht die Datei automatisch anhand der Systemeinstellungen zu dekodieren. Python 2.x dagegen liest in diesem Fall einfach Bytes, um Unicode-Objekte daraus zu erhalten, muss man entweder auf das codecs-Modul zurückgreifen, oder manuell dekodieren.
3. Unicode ist einfach eine Tabelle mit allen möglichen Zeichen und UTF-8 eine Möglichkeit diese digital zu speichern?
Ja. Eine andere Möglichkeit, Unicode-Zeichen zu speichern, wäre beispielsweise UTF-16.
4. Ich habe gelesen 1 Zeichen braucht 1Byte, aber nur wenn man es in ASCII kodiert, oder?
Ja.
Bei UTF-8 nur wenn das Zeichen im ASCII-Code vorkommt, richtig?
Ja.
(also sich als 1 Byte darstellen lässt (also <128))
Es lassen sich auch Zeichen größer als 128 in einem Byte darstellen, der Wertebereich eines Bytes reicht von 2**0 bis 2**8-1
5. Warum wird folgende Exception geworfen
SyntaxError: Non-ASCII character
wenn ich ohne ein Encoding anzugeben die Datei mit Sonderzeichen ausführen möchte? Was hat das mit ASCII zu tuen?
Python kann nicht wissen, in welcher Kodierung die Datei gespeichert wurde. Python 2.x geht den "sichersten" Weg und dekodiert mit ASCII. Python 3 nutzt UTF-8.

Um die Kodierung der Python-Datei anzugeben, gibt es das Encoding-Cookie am Anfang der Datei.
Ich dachte Python nimmt standartmäßig alles Unicode?
"Unicode" ist keine Kodierung, eine Datei ist nicht "Unicode", sondern "UTF-8" oder "UTF-16".
Benutzeravatar
Dr.Miles
User
Beiträge: 38
Registriert: Montag 15. Dezember 2008, 08:33
Wohnort: Mannheim
Kontaktdaten:

lunar hat geschrieben:"Unicode" ist keine Kodierung, eine Datei ist nicht "Unicode", sondern "UTF-8" oder "UTF-16".
So las ich das zuerst auch, aber in dem oben schon verlinkten Beitrag lese ich es anderst:
gerold hat geschrieben: Umwandeln zwischen den verschiedenen Encodings

Python verwendet als Basis Unicode! So kurz dieser Satz auch ist, so wichtig ist er. Möchte man einen Text von einem Encoding in ein anderes Umwandeln, dann geschieht das in zwei Schritten.

Code: Alles auswählen

iso-8859-1  -->  Unicode  -->  utf-8
utf-8       -->  Unicode  -->  iso-8859-1
...
Die Umwandlung nach Unicode wird von decode() und die Umwandlung von Unicode in ein anderes Encoding wird von encode() erledigt.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

# Text definieren
s_iso88591 = "Hallo Österreich"

# Text nach Unicode umwandeln
s_unicode = s_iso88591.decode("iso-8859-1")

# Text nach UTF-8 umwandeln
s_utf8 = s_unicode.encode("utf-8")

print type(s_iso88591)
print type(s_unicode)
print type(s_utf8)
...
[/quote]
Was ist da gemeint? Da steht ja explizit einmal nach Unicode umwandeln und einaml nach UTF-8 ...

Gruß
Dr.Miles
www.i2p2.de <--- sehr interressantes Anonymisierungsprojekt.
www.schaeuble-wegtreten.de <--- Petition gegen Schäuble
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Das stimmt schon so.

Du kannst es dir vorstellen wie ein Bild dass du einscannst, verarbeitest und dann ausdruckst:

Bild -(encode/scan)-> JPEG -(decode/print)-> Bild

Dabei ist JPEG die abstrakte Form, genauso wie Unicode die abstrakte Form für Character ist. Es ist vielleicht etwas unklar, dass Unicode an sich kein Encoding ist sondern eben nur eine Tabelle die Zeichen auf Codepoints abbildet.

Wie ich grade merke ist die Analogie gar nicht mal so schlecht, denn du kannst auch verschiedene Drucker verwenden (s/w Laserdrucker, Farblaser, Tintenstrahler, Photodrucker, Plotter die den Encodings entsprechen) und je nach Druckertyp sieht dein Ausgabebild anders aus.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Dr.Miles
User
Beiträge: 38
Registriert: Montag 15. Dezember 2008, 08:33
Wohnort: Mannheim
Kontaktdaten:

Leonidas hat geschrieben: Bild -(encode/scan)-> JPEG -(decode/print)-> Bild
Nach diesem Muster (Beispiel mit Buchstabe Ü):
8895-1 ---> Unicode ---> UTF-8
DC ---> U+00220---> C39C

Python wandelt also alles was es bearbeitet intern nach Unicode um. Wenn kein encoding angegeben wurde interpretiert Python(2.x) standartmäßig alles als ASCII,
deswegen die Exception(Non-ASCII character). Wenn ich ein encoding angebe,
dann "denkt" Python: ah, bei dieser datei steht dabei wie sie codiert ist, also
nehme ich nicht den Standart (ASCII ---> Unicode) sondern (beispielsweise)
UTF-8 ---> Unicode.
Was mir nicht ganz klar ist: Python muss intern die Tabelle ja auch irgendwie
darstellen(Binär), warum nimmt man nicht direkt diese Art der Darstellung zum
speichern? Weil UTF-8 genormt ist und Unicode-Tabellen auf verschiedene Art abgebildet werden können?
Noch eins: Vewendet Scite als Standartcoding unter Ubuntu 8895-1?
Wenn ich im Scite Encoding auf "Code Page Property" stelle, ein Ü eingebe und auf UTF-8 wechsle, dann zeigt er mir dieses Symbol:
Bild
und wenn ich von UTF-8 zurück auf "Code Page Property" stelle, dann sieht es so aus:
Bild
Ersteres Bild ist UTF-8 Ansicht des mit "Code Page Property" erstellten Ü`s, ein "Dingens" wo DC drinsteht, der 8895-1-Code für Ü... Was heisst den Code Page property? Ich würde sowas wie "Standart" tippen, das ist auf meinem System allerdings UTF-8:
ni@Leibeigener:~$ /usr/bin/locale
LANG=de_DE.UTF-8
LC_CTYPE="de_DE.UTF-8"
LC_NUMERIC="de_DE.UTF-8"
LC_TIME="de_DE.UTF-8"
LC_COLLATE="de_DE.UTF-8"
LC_MONETARY="de_DE.UTF-8"
LC_MESSAGES="de_DE.UTF-8"
LC_PAPER="de_DE.UTF-8"
LC_NAME="de_DE.UTF-8"
LC_ADDRESS="de_DE.UTF-8"
LC_TELEPHONE="de_DE.UTF-8"
LC_MEASUREMENT="de_DE.UTF-8"
LC_IDENTIFICATION="de_DE.UTF-8"
LC_ALL=
ni@Leibeigener:~$
Also heisst Code Page Property gleich 8895-1? Wär ja Quatsch, dann würd ja 8895-1 da stehen oder?
www.i2p2.de <--- sehr interressantes Anonymisierungsprojekt.
www.schaeuble-wegtreten.de <--- Petition gegen Schäuble
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Dr.Miles hat geschrieben:Python wandelt also alles was es bearbeitet intern nach Unicode um.
Nein, Python 2.x nicht, da muss es der Programmierer tun.
Dr.Miles hat geschrieben:Wenn ich ein encoding angebe, dann "denkt" Python: ah, bei dieser datei steht dabei wie sie codiert ist, also nehme ich nicht den Standart (ASCII ---> Unicode) sondern (beispielsweise) UTF-8 ---> Unicode.
Dr.Miles hat geschrieben:Was mir nicht ganz klar ist: Python muss intern die Tabelle ja auch irgendwie darstellen(Binär), warum nimmt man nicht direkt diese Art der Darstellung zum speichern? Weil UTF-8 genormt ist und Unicode-Tabellen auf verschiedene Art abgebildet werden können?
Intern wird UCS-2 oder UCS-4 verwendet (je nachdem wie es kompiliert wurde), wobei UCS-4 das gleiche ist wie UTF-32. Aber niemand würde normal Daten in UTF-32 Speichern, weil das einfach zu viel Platz wegnimmt.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Dr.Miles hat geschrieben:darstellen(Binär), warum nimmt man nicht direkt diese Art der Darstellung zum
speichern? Weil UTF-8 genormt ist und Unicode-Tabellen auf verschiedene Art abgebildet werden können?
Weil UTF-8 im westlichen Sprachraum eine kleinere Dateigröße hat(fast alle Zeichen sind normale 1-byte ASCII-Zeichen) und weil UTF-8 auch ASCII-kompatibel ist. Man kann mit einem ASCII-Programm ohne Probleme eine englische UTF-8-Datei öffnen und kann dann das meiste lesen
BlackJack

Ergänzend zu Leondas' Beitrag: *CPython* stellt Unicode intern als UCS-16 oder UCS-32 dar. Das kann bei anderen Implementierungen ganz anders aussehen. Genau da liegt der Punkt warum man das nicht zum Speichern benutzen kann: Wie das intern gehandhabt wird, ist ein Implementierungsdetail, das hat Dich nicht weiter zu interessieren. Es wäre sogar vorstellbar, dass eine Implementierung verschiedene Kodierungen nebeneinander verwendet. Zum Beispiel das je nach Zeichenkette eine platzsparende Kodierung verwendet wird, also zum Beispiel 1 Byte pro Zeichen wenn nur ASCII- oder vielleicht auch ISO-8859-1-Zeichen enthalten sind.
Benutzeravatar
Dr.Miles
User
Beiträge: 38
Registriert: Montag 15. Dezember 2008, 08:33
Wohnort: Mannheim
Kontaktdaten:

OK, danke erstmal. Hoffe wird nicht zuviel hätte noch ein paar fragen :

1)Ein Objekt str wird auch entsprechend geändert, wenn man als encoding utf-8 angibt? Nur beim einlesen der "gecookieten"-Datei, aber nicht mehr während der Laufzeit gell?
2)Also wenn ich den String aus der File auslese ja, aber was ist wenn ich ihn über raw_input() einlese und stdin steht auf iso-8859-1?
Dann hat der String 8859-1 oder?

3)Die Methode .decode() versucht ohne Parameter ASCII ---> Unicode umzuwandeln, analog versucht .encode() Unicode --> ASCII zu verwandeln?
VORSICHT! Das Encoding der Kommandozeile ist nicht das Encoding von STDIN.
4)Weil die Shell an sich mit UTF-8 arbeiten kann, aber stdin nichts anderes als ein Dateizeiger ist, der auch mit iso-8859-1 definiert sein kann?
Hat man das Encoding herausgefunden, dann sollte man sich im Programm darum kümmern, dass die Strings vor der Verwendung nach Unicode oder in das Encoding des Skriptes umgewandelt werden.
5)In das encoding des skriptes, damit man es verwenden kann wie die anderen strings auch, die kein Unicode sind?

Code: Alles auswählen

>>> b = "ü" #6)Mein stdin = UTF-8, also müsste b doch auch UTF-8 sein, richtig?
>>> print b.encode("utf-8")  #7)Nun erwartet encode ein Unicode Objekt, richtig? Da er keines ekommt sondern ein UTF-8 bringt er einen fehler
Traceback (most recent call last):#8)Aber warum einen mit ASCII im Namen? Was hat das denn mit ASCII zu tuen alles, da is doch nirgends von die rede?
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)'''
Gruß
Dr.Miles
www.i2p2.de <--- sehr interressantes Anonymisierungsprojekt.
www.schaeuble-wegtreten.de <--- Petition gegen Schäuble
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Dr.Miles hat geschrieben:1)Ein Objekt str wird auch entsprechend geändert, wenn man als encoding utf-8 angibt? Nur beim einlesen der "gecookieten"-Datei, aber nicht mehr während der Laufzeit gell?
Bis auf ein paar Ausnahmen in Python 2.x (aber nicht mehr in 3.x) wird ein String eigentlich nie automatisch dekodiert oder enkodiert. Das ist Sache des Programmierers.
Dr.Miles hat geschrieben:2)Also wenn ich den String aus der File auslese ja, aber was ist wenn ich ihn über raw_input() einlese und stdin steht auf iso-8859-1?
Dann hat der String 8859-1 oder?
Dann hast du einen ISO-8859-1 kodierten Bytestring. Es gibt aber auch die Möglichkeit dass du über den ``<`` Operator eine Datei reinleitest, in dem Fall ist das Eingabeencoding das Encoding der Datei. Ist ja auch logisch die Shell ändert das Encoding nicht sondern behandelt das quasi wie Binärdaten.
Dr.Miles hat geschrieben:3)Die Methode .decode() versucht ohne Parameter ASCII ---> Unicode umzuwandeln, analog versucht .encode() Unicode --> ASCII zu verwandeln?
Ja, aber da hättest du auch die Hilfe konsultieren können, da steht so etwas drin.
Dr.Miles hat geschrieben:4)Weil die Shell an sich mit UTF-8 arbeiten kann, aber stdin nichts anderes als ein Dateizeiger ist, der auch mit iso-8859-1 definiert sein kann?
Ja, in etwa.
Dr.Miles hat geschrieben:
Hat man das Encoding herausgefunden, dann sollte man sich im Programm darum kümmern, dass die Strings vor der Verwendung nach Unicode oder in das Encoding des Skriptes umgewandelt werden.
5)In das encoding des skriptes, damit man es verwenden kann wie die anderen strings auch, die kein Unicode sind?
In Unicode verwandeln. Vergiss den Teil mit "in das Encoding des Skriptes" kopieren, das ist Quatsch. String-Operationen auf Strings machen mehr Sinn als welche auf Bytestrings, da es dort eine Zuordnung von Buchstabe zu Codepoint gibt, und bei Bytestrings nicht, somit kann zum Beispiel die Länge "falsch" sein.

Dr.Miles hat geschrieben:

Code: Alles auswählen

>>> b = "ü" #6)Mein stdin = UTF-8, also müsste b doch auch UTF-8 sein, richtig?
>>> print b.encode("utf-8")  #7)Nun erwartet encode ein Unicode Objekt, richtig? Da er keines ekommt sondern ein UTF-8 bringt er einen fehler
Traceback (most recent call last):#8)Aber warum einen mit ASCII im Namen? Was hat das denn mit ASCII zu tuen alles, da is doch nirgends von die rede?
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)'''
Nein, du musst einfach ``decode`` verwenden (siehe oben wo du selbst gesagt hast dass ``decode`` von ``encoding`` nach Unicode konvertiert), dann stimmt das schon.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten