In Fortsetzung des Artikels Gestern werde ich diesmal meine eigene Richtlinie beim Umgang mit Zeichenketten in Python3 zusammenfassen.
Das ist nicht gut oder schlecht, es gibt nur nicht viele Fälle, in denen Sie sich mit Bytes in Ihrem Code befassen müssen.
Die Byte-Zeichenfolge wird durch eine bestimmte Codierungsmethode codiert und im Literal als "b'a" ausgedrückt. Andererseits ist eine Zeichenfolge ein Array von Unicode-Codepunkten und wird in Literalen als "a" ausgedrückt.
Ich habe es kurz geschrieben, aber an dieser Stelle können Sie den Unterschied im Umgang mit Python 2 erkennen.
python
(py3.4)~ » ipython
(Kürzung)
>>> b'a' #Byte-String
Out[1]: b'a'
#Die Literalschreibweise kann nicht verwendet werden, wenn Nicht-ASCII-Zeichen enthalten sind
#Die Zeichenfolge muss mit einer bestimmten Codierungsmethode codiert werden
>>> b'Ah'
File "<ipython-input-2-c12eb8e58bcd>", line 1
b'Ah'
^
SyntaxError: bytes can only contain ASCII literal characters.
>>> 'Ah'.encode('utf-8') #String->Byte-String(Kodieren)
Out[3]: b'\xe3\x81\x82'
>>> 'Ah' #String
Out[4]: 'Ah'
>>> b'\xe3\x81\x82'.decode('utf-8') #Byte-String->String(Dekodieren)
Out[5]: 'Ah'
# Python2(Erneut veröffentlichen)
(py2.7)~ » ipython
(Kürzung)
>>> 'Ah' #Byte-String
Out[1]: '\xe3\x81\x82'
>>> u'Ah' #Unicode-Zeichenfolge
Out[2]: u'\u3042'
>>> 'Ah'.decode('utf-8') (or unicode('Ah', 'utf-8')) #Byte-String->Unicode-Zeichenfolge(=Dekodieren)
Out[3]: u'\u3042'
>>> u'Ah'.encode('utf-8') #Unicode-Zeichenfolge->Byte-String(=Kodieren)
Out[4]: '\xe3\x81\x82'
Wenn Sie mit der Funktion "Typ" prüfen, können Sie feststellen, dass die Byte-Zeichenfolge vom Typ "Bytes" / die Zeichenfolge vom Typ "Str" ist.
python
>>> type(b'a')
Out[6]: bytes #≒ Python2-Str-Typ
>>> type('a')
Out[7]: str #≒ Python2-Unicode-Typ
Wie oben erwähnt, sind Python3-Byte-Zeichenfolgen keine "Zeichenfolgen". Daher kann es nicht mit einer Zeichenfolge verkettet werden, und die unterstützten Methoden unterscheiden sich. Dieser Punkt ist relativ wichtig, da es sich um dieselbe Zeichenfolge wie in Python2 handelt, die Verarbeitung irgendwie fortschreitet und schließlich "UnicodeEncodeError is ga", in Python3 jedoch "Fehler aufgrund unterschiedlichen Typs" und Fehlerausgabe / Der Ort des Auftretens ist relativ leicht zu verstehen.
python
>>> s = 'str' #String
>>> b = b'byte' #Byte-String
>>> s + b #String+Byte-String ist ein Fehler
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-20-5fe2240a1b50> in <module>()
----> 1 s + b
TypeError: Can't convert 'bytes' object to str implicitly
>>> s.find('t') #Die Zeichenfolge unterstützt die Suchmethode
Out[11]: 1
>>> b.find('y') #Die Byte-Zeichenfolge unterstützt die Suchmethode nicht.
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-24-e1b070a5aaba> in <module>()
----> 1 b.find('y')
TypeError: Type str doesn't support the buffer API
Ab Python 3.2 scheint es auch dann die geeignete Codierungsmethode aus dem Wert des Gebietsschemas auszuwählen, wenn die Standardausgabe mit einem anderen als dem Terminal verbunden ist. Daher funktionieren in Python2 die folgenden Fälle mit UnicodeEncodeError ebenfalls normal.
(Ref.) http://methane.hatenablog.jp/entry/20120806/1344269400 Nachtrag
python
(py3.4)~ » cat test.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
print('Ah' + 'Sagen')
#Im Terminal ausführen(Der Standardeingang / -ausgang ist mit dem Terminal verbunden)
(py3.4)~ » python test.py
Ah
#In Datei umleiten(Der Standardeingang / -ausgang ist nicht mit dem Terminal verbunden)
(py3.4)~ » python test.py > test.txt
(py3.4)~ » cat test.txt
Ah
Auch wenn Sie Ihren Tod nicht offenkundig melden, können Sie dennoch auf einen UnicodeEncodeError stoßen. Wenn Sie beispielsweise von cron aus ausführen, können Sie die Codierungsmethode nicht aus dem Gebietsschema auswählen und versuchen, mit ASCII zu codieren / decodieren, und Sie erhalten normalerweise UnicodeEncodeError.
(ref.) http://www.python.jp/pipermail/python-ml-jp/2014-November/011311.html (Die Veröffentlichung erfolgt äußerst zeitnah)
In Anbetracht dieser Dinge ist es möglicherweise besser, die Codierungsmethode immer mit der Umgebungsvariablen "PYTHONIOENCODING" anzugeben, ohne sich auf das Gebietsschema zu verlassen.
(ref.) http://methane.hatenablog.jp/entry/20120806/1344269400 (ref.) http://www.python.jp/pipermail/python-ml-jp/2014-November/011314.html
Sie können sys.stdin.buffer
(Standardeingabe) / sys.stdout.buffer
(Standardeingabe) verwenden, um Byte-Strings anstelle von Strings zu verarbeiten.
python
(py3.4)~ » cat test.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
#print('Ah' + 'Sagen') #Druck ist sys.Schreiben Sie an stdout
sys.stdout.write('Ah' + 'Sagen' + '\n') # sys.Schreiben Sie eine Zeichenfolge in stdout
sys.stdout.buffer.write(('Ah' + 'Sagen' + '\n').encode('utf-8')) # sys.stdout.Schreiben Sie eine Zeichenfolge von Bytes zum Puffern
#Im Terminal ausführen
(py3.4)~ » python test.py
Ah
Ah
#In Datei umleiten
(py3.4)~ » python test.py > test.txt
(py3.4)~ » cat test.txt
Ah
Ah
Auch in Python 3 sind Bytes und Strings völlig unterschiedlich. Daher kann die Bytezeichenfolge nicht in "sys.stdout" geschrieben werden, das die Zeichenfolge schreibt, und die Zeichenfolge kann nicht in "sys.stdout.buffer" geschrieben werden, in das die Bytezeichenfolge geschrieben wird.
python
>>> import sys
#Textstrom(ref. https://docs.python.org/3/library/io.html#io.TextIOWrapper)
>>> type(sys.stdout)
Out[2]: _io.TextIOWrapper
#Byte-Stream(ref. https://docs.python.org/3/library/io.html#io.BufferedWriter)
>>> type(sys.stdout.buffer)
Out[3]: _io.BufferedWriter
#Bytes können nicht in den Textstrom geschrieben werden
>>> sys.stdout.write('a'.encode('utf-8'))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-4-581ae8b6af82> in <module>()
----> 1 sys.stdout.write('a'.encode('utf-8'))
TypeError: must be str, not bytes
#Strings können nicht in bytestream geschrieben werden
>>> sys.stdout.buffer.write('a')
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-5-42da1d141b96> in <module>()
----> 1 sys.stdout.buffer.write('a')
TypeError: 'str' does not support the buffer interface