W Pythonie 3 wszystkie ciągi są ciągami znaków Unicode. Istnieje bytestyp przechowujący nieprzetworzone bajty.
W Pythonie 2 łańcuch może być typu strlub typu unicode. Możesz stwierdzić, który kod używa czegoś takiego:
def whatisthis(s):if isinstance(s, str):print"ordinary string"elif isinstance(s, unicode):print"unicode string"else:print"not a string"
Nie rozróżnia to „Unicode lub ASCII”; rozróżnia tylko typy Pythona. Łańcuch Unicode może składać się wyłącznie z znaków w zakresie ASCII, a bajtowanie może zawierać ASCII, kodowany Unicode, a nawet dane nietekstowe.
W Python 2 strjest tylko sekwencją bajtów. Python nie wie, jakie jest jego kodowanie. Ten unicodetyp jest bezpieczniejszym sposobem przechowywania tekstu. Jeśli chcesz to lepiej zrozumieć, polecam http://farmdev.com/talks/unicode/ .
W Pythonie 3 strjest podobny do Pythona 2 unicodei służy do przechowywania tekstu. To, co nazywa się strw Pythonie 2, nazywa się bytesw Pythonie 3.
Jak stwierdzić, czy łańcuch bajtów jest poprawny utf-8 czy ascii
Można zadzwonić decode. Jeśli zgłosi wyjątek UnicodeDecodeError, nie jest prawidłowy.
>>> u_umlaut = b'\xc3\x9c'# UTF-8 representation of the letter 'Ü'>>> u_umlaut.decode('utf-8')
u'\xdc'>>> u_umlaut.decode('ascii')Traceback(most recent call last):File"<stdin>", line 1,in<module>UnicodeDecodeError:'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)
Tylko dla odniesienia innych osób - str.decode nie istnieje w Pythonie 3. Wygląda na to, że musisz unicode(s, "ascii")czy coś
Shadow
3
Przepraszam, miałem na myślistr(s, "ascii")
Shadow
1
To nie jest dokładne dla Pythona 3
ProsperousHeart
2
@ProsperousHeart Zaktualizowano, aby objąć Python 3. I spróbować wyjaśnić różnicę między bajtowaniem i ciągami Unicode.
Mikel
44
W Pythonie 3.x wszystkie ciągi są ciągami znaków Unicode. i wykonanie sprawdzania isinstance dla str (co domyślnie oznacza ciąg Unicode) powinno wystarczyć.
isinstance(x, str)
Jeśli chodzi o Python 2.x, większość osób wydaje się używać instrukcji if, która ma dwa testy. jeden dla str i jeden dla unicode.
Jeśli chcesz sprawdzić, czy masz obiekt „podobny do łańcucha” za pomocą jednej instrukcji, możesz wykonać następujące czynności:
To nieprawda. W Python 2.7 isinstance(u"x",basestring)zwraca True.
PythonNut
11
@PythonNut: Myślę, że o to właśnie chodziło. Zastosowanie isinstance (x, basestring) wystarcza, aby zastąpić odrębne podwójne testy powyżej.
KQ.
5
Jest to przydatne w wielu przypadkach, ale najwyraźniej nie to, co miał na myśli pytający.
mhsmith,
3
To jest odpowiedź na pytanie. Wszyscy inni źle zrozumieli słowa OP i udzielili ogólnych odpowiedzi na temat sprawdzania typów w Pythonie.
fiatjaf
1
Nie odpowiada na pytanie OP. Tytuł pytania (sam) MUSI być interpretowany w taki sposób, aby odpowiedź była poprawna. Jednak OP wyraźnie mówi „dowiedzieć się, które” w opisie pytania, a ta odpowiedź nie rozwiązuje tego.
MD004
31
Unicode nie jest kodowaniem - cytując Kumara McMillana:
Jeśli ASCII, UTF-8 i inne ciągi bajtów są „tekstem” ...
Te slajdy są prawdopodobnie najlepszym wprowadzeniem do Unicode, z jakim się spotkałem
Jonny
23
Jeśli twój kod musi być kompatybilny zarówno z Python 2, jak i Python 3, nie możesz bezpośrednio używać rzeczy takich jak isinstance(s,bytes)lub isinstance(s,unicode)bez owijania ich w try / try lub w testach wersji Python, ponieważ bytesjest niezdefiniowany w Pythonie 2 i unicodeniezdefiniowany w Pythonie 3 .
Istnieje kilka brzydkich obejść. Niezwykle brzydkie jest porównywanie nazwy typu zamiast porównywania samego typu. Oto przykład:
# convert bytes (python 3) or unicode (python 2) to strif str(type(s))=="<class 'bytes'>":# only possible in Python 3
s = s.decode('ascii')# or s = str(s)[2:-1]elif str(type(s))=="<type 'unicode'>":# only possible in Python 2
s = str(s)
Prawdopodobnie nieco mniej brzydkim obejściem jest sprawdzenie numeru wersji Pythona, np .:
if sys.version_info >=(3,0,0):# for Python 3if isinstance(s, bytes):
s = s.decode('ascii')# or s = str(s)[2:-1]else:# for Python 2if isinstance(s, unicode):
s = str(s)
Oba są niepytoniczne i przez większość czasu jest prawdopodobnie lepszy sposób.
Lepszym sposobem jest prawdopodobnie do użytku six, a testy przed six.binary_typeisix.text_type
Ian Clelland
1
Możesz użyć type (s) .__ name__ do sondowania nazw typów.
Paulo Freitas
Nie jestem całkowicie pewien przypadku użycia tego fragmentu kodu, chyba że wystąpił błąd logiczny. Myślę, że w kodzie python 2 powinno być „nie”. W przeciwnym razie konwertujesz wszystko na ciągi Unicode dla Python 3 i odwrotnie dla Python 2!
oligofren
Tak, oligofren, właśnie to robi. Standardowymi ciągami wewnętrznymi są Unicode w Pythonie 3 i ASCII w Pythonie 2. Więc fragmenty kodu konwertują tekst na standardowy wewnętrzny ciąg znaków (czy to Unicode, czy ASCII).
Dave Burton
12
posługiwać się:
import six
if isinstance(obj, six.text_type)
wewnątrz sześciu bibliotek jest reprezentowany jako:
if PY3:
string_types = str,else:
string_types = basestring,
tak powinno być if isinstance(obj, six.text_type) . Ale tak, to imo poprawna odpowiedź.
karantan
Nie odpowiada na pytanie OP. Tytuł pytania (sam) MUSI być interpretowany w taki sposób, aby odpowiedź była poprawna. Jednak OP wyraźnie mówi „dowiedzieć się, które” w opisie pytania, a ta odpowiedź nie rozwiązuje tego.
MD004
4
Zauważ, że w Pythonie 3, niesprawiedliwe jest powiedzenie któregokolwiek z:
strs są UTFx dla dowolnego x (np. UTF8)
strs są Unicode
strs to uporządkowane kolekcje znaków Unicode
Python's strTyp jest (normalnie) sekwencją punktów kodu Unicode, z których niektóre są mapowane na znaki.
Nawet w Pythonie 3 odpowiedź na to pytanie nie jest tak prosta, jak można sobie wyobrazić.
Oczywistym sposobem przetestowania ciągów zgodnych z ASCII jest próba kodowania:
"Hello there!".encode("ascii")#>>> b'Hello there!'"Hello there... ☃!".encode("ascii")#>>> Traceback (most recent call last):#>>> File "", line 4, in <module>#>>> UnicodeEncodeError: 'ascii' codec can't encode character '\u2603' in position 15: ordinal not in range(128)
Błąd rozróżnia przypadki.
W Pythonie 3 są nawet niektóre ciągi znaków, które zawierają nieprawidłowe punkty kodu Unicode:
"Hello there!".encode("utf8")#>>> b'Hello there!'"\udcc3".encode("utf8")#>>> Traceback (most recent call last):#>>> File "", line 19, in <module>#>>> UnicodeEncodeError: 'utf-8' codec can't encode character '\udcc3' in position 0: surrogates not allowed
To może pomóc komuś innemu. Zacząłem testować typ ciągu zmiennej s, ale dla mojej aplikacji bardziej sensowne było po prostu zwrócenie s jako utf-8. Proces wywołujący return_utf, a następnie wie, z czym ma do czynienia i odpowiednio obsługuje ciąg. Kod nie jest nieskazitelny, ale zamierzam, aby był on niezależny od wersji Pythona bez testu wersji lub importowania sześciu. Skomentuj ulepszenia przykładowego kodu poniżej, aby pomóc innym osobom.
def return_utf(s):if isinstance(s, str):return s.encode('utf-8')if isinstance(s,(int, float, complex)):return str(s).encode('utf-8')try:return s.encode('utf-8')exceptTypeError:try:return str(s).encode('utf-8')exceptAttributeError:return s
exceptAttributeError:return s
return s # assume it was already utf-8
Mój przyjacielu zasługujesz na poprawną odpowiedź! Używam Pythona 3 i wciąż miałem problemy, dopóki nie znalazłem tego skarbu!
mnsr
2
Możesz użyć Universal Encoding Detector , ale pamiętaj, że pozwoli ci to odgadnąć, a nie rzeczywiste kodowanie, ponieważ nie można na przykład znać kodowania ciągu „abc”. Będziesz musiał uzyskać informacje o kodowaniu gdzie indziej, np. Protokół HTTP używa do tego nagłówka Content-Type.
Jednym prostym podejściem jest sprawdzenie, czy unicodejest to funkcja wbudowana. Jeśli tak, jesteś w Pythonie 2, a Twój ciąg znaków będzie ciągiem. Aby upewnić się, że wszystko jest w unicodeporządku, możesz:
import builtins
i ='cats'if'unicode'in dir(builtins):# True in python 2, False in 3
i = unicode(i)
{UnicodeDecodeError} 'ascii' codec can't decode byte 0xc2
Odpowiedzi:
W Pythonie 3 wszystkie ciągi są ciągami znaków Unicode. Istnieje
bytes
typ przechowujący nieprzetworzone bajty.W Pythonie 2 łańcuch może być typu
str
lub typuunicode
. Możesz stwierdzić, który kod używa czegoś takiego:Nie rozróżnia to „Unicode lub ASCII”; rozróżnia tylko typy Pythona. Łańcuch Unicode może składać się wyłącznie z znaków w zakresie ASCII, a bajtowanie może zawierać ASCII, kodowany Unicode, a nawet dane nietekstowe.
źródło
Jak stwierdzić, czy obiekt jest łańcuchem Unicode czy ciągiem bajtów
Możesz użyć
type
lubisinstance
.W Python 2:
W Python 2
str
jest tylko sekwencją bajtów. Python nie wie, jakie jest jego kodowanie. Tenunicode
typ jest bezpieczniejszym sposobem przechowywania tekstu. Jeśli chcesz to lepiej zrozumieć, polecam http://farmdev.com/talks/unicode/ .W Pythonie 3:
W Pythonie 3
str
jest podobny do Pythona 2unicode
i służy do przechowywania tekstu. To, co nazywa sięstr
w Pythonie 2, nazywa siębytes
w Pythonie 3.Jak stwierdzić, czy łańcuch bajtów jest poprawny utf-8 czy ascii
Można zadzwonić
decode
. Jeśli zgłosi wyjątek UnicodeDecodeError, nie jest prawidłowy.źródło
unicode(s, "ascii")
czy cośstr(s, "ascii")
W Pythonie 3.x wszystkie ciągi są ciągami znaków Unicode. i wykonanie sprawdzania isinstance dla str (co domyślnie oznacza ciąg Unicode) powinno wystarczyć.
Jeśli chodzi o Python 2.x, większość osób wydaje się używać instrukcji if, która ma dwa testy. jeden dla str i jeden dla unicode.
Jeśli chcesz sprawdzić, czy masz obiekt „podobny do łańcucha” za pomocą jednej instrukcji, możesz wykonać następujące czynności:
źródło
isinstance(u"x",basestring)
zwracaTrue
.Unicode nie jest kodowaniem - cytując Kumara McMillana:
Przeczytaj Unicode McMillana W Pythonie, całkowicie zdemistalizowanym wykładzie z PyCon 2008, wyjaśnia on rzeczy znacznie lepiej niż większość powiązanych odpowiedzi na temat przepełnienia stosu.
źródło
Jeśli twój kod musi być kompatybilny zarówno z Python 2, jak i Python 3, nie możesz bezpośrednio używać rzeczy takich jak
isinstance(s,bytes)
lubisinstance(s,unicode)
bez owijania ich w try / try lub w testach wersji Python, ponieważbytes
jest niezdefiniowany w Pythonie 2 iunicode
niezdefiniowany w Pythonie 3 .Istnieje kilka brzydkich obejść. Niezwykle brzydkie jest porównywanie nazwy typu zamiast porównywania samego typu. Oto przykład:
Prawdopodobnie nieco mniej brzydkim obejściem jest sprawdzenie numeru wersji Pythona, np .:
Oba są niepytoniczne i przez większość czasu jest prawdopodobnie lepszy sposób.
źródło
six
, a testy przedsix.binary_type
isix.text_type
posługiwać się:
wewnątrz sześciu bibliotek jest reprezentowany jako:
źródło
if isinstance(obj, six.text_type)
. Ale tak, to imo poprawna odpowiedź.Zauważ, że w Pythonie 3, niesprawiedliwe jest powiedzenie któregokolwiek z:
str
s są UTFx dla dowolnego x (np. UTF8)str
s są Unicodestr
s to uporządkowane kolekcje znaków UnicodePython's
str
Typ jest (normalnie) sekwencją punktów kodu Unicode, z których niektóre są mapowane na znaki.Nawet w Pythonie 3 odpowiedź na to pytanie nie jest tak prosta, jak można sobie wyobrazić.
Oczywistym sposobem przetestowania ciągów zgodnych z ASCII jest próba kodowania:
Błąd rozróżnia przypadki.
W Pythonie 3 są nawet niektóre ciągi znaków, które zawierają nieprawidłowe punkty kodu Unicode:
Zastosowano tę samą metodę ich rozróżnienia.
źródło
To może pomóc komuś innemu. Zacząłem testować typ ciągu zmiennej s, ale dla mojej aplikacji bardziej sensowne było po prostu zwrócenie s jako utf-8. Proces wywołujący return_utf, a następnie wie, z czym ma do czynienia i odpowiednio obsługuje ciąg. Kod nie jest nieskazitelny, ale zamierzam, aby był on niezależny od wersji Pythona bez testu wersji lub importowania sześciu. Skomentuj ulepszenia przykładowego kodu poniżej, aby pomóc innym osobom.
źródło
Możesz użyć Universal Encoding Detector , ale pamiętaj, że pozwoli ci to odgadnąć, a nie rzeczywiste kodowanie, ponieważ nie można na przykład znać kodowania ciągu „abc”. Będziesz musiał uzyskać informacje o kodowaniu gdzie indziej, np. Protokół HTTP używa do tego nagłówka Content-Type.
źródło
Aby uzyskać zgodność z py2 / py3, wystarczy użyć
import six if isinstance(obj, six.text_type)
źródło
Jednym prostym podejściem jest sprawdzenie, czy
unicode
jest to funkcja wbudowana. Jeśli tak, jesteś w Pythonie 2, a Twój ciąg znaków będzie ciągiem. Aby upewnić się, że wszystko jest wunicode
porządku, możesz:źródło