Verwendung der Funktionen unicode () und encode () in Python

83

Ich habe ein Problem mit der Codierung des Pfades variabel und an die Einfügen von SQLite - Datenbank. Ich habe versucht, es mit der Codierungsfunktion ("utf-8") zu lösen, was nicht geholfen hat. Dann habe ich die Funktion unicode () verwendet, die mir den Typ unicode gibt .

print type(path)                  # <type 'unicode'>
path = path.replace("one", "two") # <type 'str'>
path = path.encode("utf-8")       # <type 'str'> strange
path = unicode(path)              # <type 'unicode'>

Schließlich habe ich Unicode - Typ, aber ich habe immer den gleichen Fehler haben , die vorhanden war , als der Typ der Pfad - Variable war str

sqlite3.ProgrammingError: Sie dürfen keine 8-Bit-Bytestrings verwenden, es sei denn, Sie verwenden eine text_factory, die 8-Bit-Bytestrings interpretieren kann (wie text_factory = str). Es wird dringend empfohlen, stattdessen nur Ihre Anwendung auf Unicode-Zeichenfolgen umzustellen.

Können Sie mir helfen, diesen Fehler zu beheben und die korrekte Verwendung encode("utf-8")und unicode()Funktionen zu erklären ? Ich kämpfe oft damit.

BEARBEITEN:

Diese execute () - Anweisung hat den Fehler ausgelöst:

cur.execute("update docs set path = :fullFilePath where path = :path", locals())

Ich habe vergessen, die Codierung der Variablen fullFilePath zu ändern, die unter demselben Problem leidet, bin aber jetzt ziemlich verwirrt. Sollte ich nur Unicode () oder Encode ("utf-8") oder beides verwenden?

Ich kann nicht verwenden

fullFilePath = unicode(fullFilePath.encode("utf-8"))

weil es diesen Fehler auslöst:

UnicodeDecodeError: Der Codec 'ascii' kann das Byte 0xc5 an Position 32 nicht dekodieren: Ordnungszahl nicht im Bereich (128)

Die Python- Version ist 2.7.2

xralf
quelle
Wo ist der Code, der den Fehler auslöst?
Newtover
2
Ihre genaue Frage wurde bereits beantwortet: [ stackoverflow.com/questions/2392732/… [1]: stackoverflow.com/questions/2392732/…
garnertb
@newtover Ich habe die Frage bearbeitet.
Xralf
Haben Sie beide verwendeten Variablen in konvertiert unicode?
Newtover
2
Das Erlernen des Umgangs mit Text und Daten in Python 3 hat mir wirklich geholfen, alles zu verstehen. Es ist dann einfach, das Wissen auf Python 2 anzuwenden.
Oleh Prypin

Antworten:

87

Sie verwenden encode("utf-8")falsch. Python-Byte-Strings ( strTyp) haben eine Codierung, Unicode nicht. Sie können uni.encode(encoding)eine Unicode-Zeichenfolge mithilfe von s.decode(encoding)(oder gleichwertig unicode(s, encoding)) in eine Python-Byte-Zeichenfolge konvertieren und eine Byte-Zeichenfolge in eine Unicode-Zeichenfolge konvertieren .

Wenn fullFilePathund pathderzeit ein strTyp sind, sollten Sie herausfinden, wie sie codiert sind. Wenn die aktuelle Codierung beispielsweise utf-8 ist, würden Sie Folgendes verwenden:

path = path.decode('utf-8')
fullFilePath = fullFilePath.decode('utf-8')

Wenn dies das Problem nicht behebt, besteht das eigentliche Problem möglicherweise darin, dass Sie in Ihrem execute()Aufruf keine Unicode-Zeichenfolge verwenden . Versuchen Sie, diese wie folgt zu ändern:

cur.execute(u"update docs set path = :fullFilePath where path = :path", locals())
Andrew Clark
quelle
Diese Aussage fullFilePath = fullFilePath.decode("utf-8")löst immer noch einen Fehler aus UnicodeEncodeError: 'ascii' codec can't encode characters in position 32-34: ordinal not in range(128). fullFilePath ist eine Kombination aus Typ str und Zeichenfolge aus genommen Textspalte DB - Tabelle , die UTF-8 - Codierung sein sollte.
Xralf
Nach diesem , aber es kann UTF-8, UTF-16 BE oder UTF-16LE sein. Kann ich es irgendwie herausfinden?
Xralf
@xralf, Wenn Sie verschiedene strObjekte kombinieren , mischen Sie möglicherweise Codierungen. Können Sie das Ergebnis von zeigen print repr(fullFilePath)?
Andrew Clark
Ich kann es nur vor dem Aufruf von decode () zeigen . Die problematischen Zeichen sind \ u0161 und \ u0165.
Xralf
@xralf - Also ist es schon Unicode? Versuchen Sie, den Ausführungsaufruf in Unicode zu ändern:cur.execute(u"update docs set path = :fullFilePath where path = :path", locals())
Andrew Clark
120

strist eine Textdarstellung in Bytes, unicodeist eine Textdarstellung in Zeichen.

Sie dekodieren Text von Bytes zu Unicode und codieren einen Unicode mit einer gewissen Codierung in Bytes.

Das ist:

>>> 'abc'.decode('utf-8')  # str to unicode
u'abc'
>>> u'abc'.encode('utf-8') # unicode to str
'abc' 
Newtover
quelle
1
Sehr gute Antwort, direkt auf den Punkt. Ich würde hinzufügen, dass unicodeüber Buchstaben oder Symbole oder allgemeiner gesprochen wird: Runen, während strsie eine Byte-Zeichenfolge in einer bestimmten Codierung darstellen, die Sie decode(offensichtlich in der richtigen Codierung)
benötigen
1

Stellen Sie sicher, dass Sie Ihre Gebietsschemaeinstellungen direkt vor dem Ausführen des Skripts über die Shell festgelegt haben, z

$ locale -a | grep "^en_.\+UTF-8"
en_GB.UTF-8
en_US.UTF-8
$ export LC_ALL=en_GB.UTF-8
$ export LANG=en_GB.UTF-8

Docs: man locale, man setlocale.

Kenorb
quelle