it-swarm.com.de

Schreiben von Unicode-Text in eine Textdatei?

Ich ziehe Daten aus einem Google-Dokument, verarbeite sie und schreibe sie in eine Datei (die ich schließlich in eine Wordpress Seite) einfügen werde).

Es enthält einige Nicht-ASCII-Symbole. Wie kann ich diese sicher in Symbole konvertieren, die in HTML-Quellen verwendet werden können?

Momentan konvertiere ich alles auf dem Weg in Unicode, füge alles in einem Python String zusammen und mache dann:

import codecs
f = codecs.open('out.txt', mode="w", encoding="iso-8859-1")
f.write(all_html.encode("iso-8859-1", "replace"))

In der letzten Zeile ist ein Codierungsfehler aufgetreten:

UnicodeDecodeError: 'ascii' Codec kann Byte 0xa0 an Position 12286 nicht decodieren: Ordnungszahl nicht im Bereich (128)

Teillösung:

Dies Python läuft ohne Fehler:

row = [unicode(x.strip()) if x is not None else u'' for x in row]
all_html = row[0] + "<br/>" + row[1]
f = open('out.txt', 'w')
f.write(all_html.encode("utf-8"))

Aber wenn ich dann die eigentliche Textdatei öffne, sehe ich viele Symbole wie:

Qur’an 

Vielleicht muss ich etwas anderes als eine Textdatei schreiben?

214
simon

Behandeln Sie Unicode-Objekte so weit wie möglich ausschließlich, indem Sie Dinge zu Unicode-Objekten decodieren, wenn Sie sie zum ersten Mal erhalten, und sie beim Verlassen nach Bedarf codieren.

Wenn Ihre Zeichenfolge tatsächlich ein Unicode-Objekt ist, müssen Sie sie in ein Unicode-codiertes Zeichenfolgenobjekt konvertieren, bevor Sie sie in eine Datei schreiben können:

foo = u'Δ, Й, ק, ‎ م, ๗, あ, 叶, 葉, and 말.'
f = open('test', 'w')
f.write(foo.encode('utf8'))
f.close()

Wenn Sie diese Datei erneut lesen, erhalten Sie eine Unicode-codierte Zeichenfolge, die Sie in ein Unicode-Objekt decodieren können:

f = file('test', 'r')
print f.read().decode('utf8')
306
quasistoic

In Python 2.6+ kannst du benutze io.open() das ist default ( builtin open() ) am Python 3:

import io

with io.open(filename, 'w', encoding=character_encoding) as file:
    file.write(unicode_text)

Es ist möglicherweise praktischer, wenn Sie den Text inkrementell schreiben müssen (Sie müssen unicode_text.encode(character_encoding) nicht mehrmals aufrufen). Im Gegensatz zum codecs -Modul bietet das io -Modul eine ordnungsgemäße Unterstützung für universelle Zeilenumbrüche.

67
jfs

Die Behandlung von Unicode-Zeichenfolgen ist in Python 3 bereits standardisiert.

  1. zeichen sind bereits in Unicode (32-Bit) gespeichert
  2. Sie müssen nur die Datei in utf-8 öffnen
    (Die 32-Bit-Konvertierung von Unicode nach utf-8 wird automatisch vom Speicher in eine Datei durchgeführt.)

    out1 = "(嘉南大圳 ㄐㄧㄚ ㄋㄢˊ ㄉㄚˋ ㄗㄨㄣˋ )"
    fobj = open("t1.txt", "w", encoding="utf-8")
    fobj.write(out1)
    fobj.close()
    
25
david m lee

Die mit codecs.open Geöffnete Datei ist eine Datei, die unicode Daten aufnimmt, in iso-8859-1 Codiert und in die Datei schreibt. Was Sie jedoch zu schreiben versuchen, ist nicht unicode; Sie nehmen unicode und kodieren es in iso-8859-1Sie selbst. Das macht die Methode unicode.encode Und das Ergebnis der Codierung eines Unicode-Strings ist ein Bytestring (ein str -Typ.)

Sie sollten entweder normales open() verwenden und den Unicode selbst codieren, oder (normalerweise eine bessere Idee) codecs.open() verwenden und nicht die Daten selbst codieren.

18
Thomas Wouters

Vorwort: Wird Ihr Viewer funktionieren?

Stellen Sie sicher, dass Ihr Viewer/Editor/Terminal (unabhängig davon, wie Sie mit Ihrer utf-8-codierten Datei interagieren) die Datei lesen kann. Dies ist häufig ein Problem bei Windows , z. B. Notepad.

Schreiben von Unicode-Text in eine Textdatei?

Verwenden Sie in Python 2 open aus dem io -Modul (dies ist dasselbe wie das in Python 3 integrierte open):

import io

Best Practice im Allgemeinen verwenden Sie UTF-8 Zum Schreiben in Dateien (wir müssen uns mit utf-8 nicht einmal um die Bytereihenfolge kümmern).

encoding = 'utf-8'

utf-8 ist die modernste und universell einsetzbare Kodierung - sie funktioniert in allen Webbrowsern, den meisten Texteditoren (sehen Sie Ihre Einstellungen, wenn Sie Probleme haben) und den meisten Terminals/Shells.

Unter Windows können Sie utf-16le Versuchen, wenn Sie die Ausgabe nur im Editor (oder in einem anderen eingeschränkten Viewer) anzeigen können.

encoding = 'utf-16le' # sorry, Windows users... :(

Und öffnen Sie es einfach mit dem Kontextmanager und schreiben Sie Ihre Unicode-Zeichen aus:

with io.open(filename, 'w', encoding=encoding) as f:
    f.write(unicode_object)

Beispiel mit vielen Unicode-Zeichen

Hier ist ein Beispiel, in dem versucht wird, jedes mögliche Zeichen mit einer Breite von bis zu drei Bit (4 ist das Maximum, aber das würde ein bisschen weit gehen) von der digitalen Darstellung (in Ganzzahlen) zu einer codierten druckbaren Ausgabe zusammen mit dem Namen abzubilden, wenn möglich (in eine Datei mit dem Namen uni.py):

from __future__ import print_function
import io
from unicodedata import name, category
from curses.ascii import controlnames
from collections import Counter

try: # use these if Python 2
    unicode_chr, range = unichr, xrange
except NameError: # Python 3
    unicode_chr = chr

exclude_categories = set(('Co', 'Cn'))
counts = Counter()
control_names = dict(enumerate(controlnames))
with io.open('unidata', 'w', encoding='utf-8') as f:
    for x in range((2**8)**3): 
        try:
            char = unicode_chr(x)
        except ValueError:
            continue # can't map to unicode, try next x
        cat = category(char)
        counts.update((cat,))
        if cat in exclude_categories:
            continue # get rid of noise & greatly shorten result file
        try:
            uname = name(char)
        except ValueError: # probably control character, don't use actual
            uname = control_names.get(x, '')
            f.write(u'{0:>6x} {1}    {2}\n'.format(x, cat, uname))
        else:
            f.write(u'{0:>6x} {1}  {2}  {3}\n'.format(x, cat, char, uname))
# may as well describe the types we logged.
for cat, count in counts.items():
    print('{0} chars of category, {1}'.format(count, cat))

Dies sollte in der Größenordnung von etwa einer Minute ausgeführt werden, und Sie können die Datendatei anzeigen. Wenn Ihr Datei-Viewer Unicode anzeigen kann, wird dies angezeigt. Informationen zu den Kategorien finden Sie hier . Aufgrund der Anzahl können wir unsere Ergebnisse wahrscheinlich verbessern, indem wir die Kategorien Cn und Co ausschließen, denen keine Symbole zugeordnet sind.

$ python uni.py

Daraufhin werden die hexadezimale Zuordnung, Kategorie , das Symbol (es sei denn, der Name kann nicht abgerufen werden, also wahrscheinlich ein Steuerzeichen) und der Name des Symbols angezeigt. z.B.

Ich empfehle less unter Unix oder Cygwin (drucke/katze nicht die gesamte Datei für deine Ausgabe):

$ less unidata

z.B. wird ähnlich den folgenden Zeilen angezeigt, die ich mit Python 2 (Unicode 5.2) abgetastet habe:

     0 Cc NUL
    20 Zs     SPACE
    21 Po  !  EXCLAMATION MARK
    b6 So  ¶  PILCROW SIGN
    d0 Lu  Ð  LATIN CAPITAL LETTER ETH
   e59 Nd  ๙  THAI DIGIT NINE
  2887 So  ⢇  BRAILLE PATTERN DOTS-1238
  bc13 Lo  밓  HANGUL SYLLABLE MIH
  ffeb Sm  →  HALFWIDTH RIGHTWARDS ARROW

Mein Python 3.5 von Anaconda hat Unicode 8.0, vermutlich die meisten 3er.

14
Aaron Hall

So drucken Sie Unicode-Zeichen in eine Datei:

Speichern Sie dies in der Datei: foo.py:

#!/usr/bin/python -tt
# -*- coding: utf-8 -*-
import codecs
import sys 
UTF8Writer = codecs.getwriter('utf8')
sys.stdout = UTF8Writer(sys.stdout)
print(u'e with obfuscation: é')

Führen Sie es aus und leiten Sie die Ausgabe in die Datei:

python foo.py > tmp.txt

Öffne tmp.txt und schau hinein, du siehst folgendes:

[email protected]:~$ cat tmp.txt 
e with obfuscation: é

So haben Sie Unicode e mit einem Verschleierungszeichen in einer Datei gespeichert.

3
Eric Leschinski

Dieser Fehler tritt auf, wenn Sie versuchen, eine Nicht-Unicode-Zeichenfolge zu codieren: Es wird versucht, sie zu decodieren, vorausgesetzt, sie ist in reinem ASCII. Es gibt zwei Möglichkeiten:

  1. Sie codieren es in einen Bytestring. Da Sie jedoch codecs.open verwendet haben, erwartet die write-Methode ein Unicode-Objekt. Sie codieren es also und es versucht erneut, es zu decodieren. Versuchen Sie stattdessen: f.write(all_html).
  2. all_html ist eigentlich kein Unicode-Objekt. Wenn Sie .encode(...) ausführen, wird zuerst versucht, es zu dekodieren.
1
Thomas K

Beim Schreiben an python3

>>> a = u'bats\u00E0'
>>> print a
batsà
>>> f = open("/tmp/test", "w")
>>> f.write(a)
>>> f.close()
>>> data = open("/tmp/test").read()
>>> data
'batsà'

Beim Schreiben an python2:

>>> a = u'bats\u00E0'
>>> f = open("/tmp/test", "w")
>>> f.write(a)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)

Um diesen Fehler zu vermeiden, müssten Sie ihn mit den folgenden Codecs "utf-8" in Bytes codieren:

>>> f.write(a.encode("utf-8"))
>>> f.close()

und dekodiere die Daten beim Lesen mit den Codecs "utf-8":

>>> data = open("/tmp/test").read()
>>> data.decode("utf-8")
u'bats\xe0'

Und auch wenn Sie versuchen, den Druckvorgang für diesen String auszuführen, wird er automatisch unter Verwendung der folgenden "utf-8" -Codecs dekodiert

>>> print a
batsà
0
ashish14