Chcę sprawdzić, czy ciąg znaków jest w ASCII, czy nie.
Jestem tego świadomy ord()
, ale kiedy próbuję ord('é')
, mam TypeError: ord() expected a character, but string of length 2 found
. Zrozumiałem, że jest to spowodowane sposobem, w jaki zbudowałem Pythona (jak wyjaśniono w ord()
dokumentacji ).
Czy istnieje inny sposób sprawdzenia?
Odpowiedzi:
źródło
ord(c) < 128
jest nieskończenie bardziej czytelny i intuicyjny niżc <= "\x7F"
Myślę, że nie zadajesz właściwego pytania ...
Łańcuch w pythonie nie ma właściwości odpowiadającej „ascii”, utf-8 lub innemu kodowaniu. Źródło łańcucha (niezależnie od tego, czy czytasz go z pliku, dane wejściowe z klawiatury itp.) Mogło zakodować łańcuch znaków Unicode w ascii, aby wygenerować łańcuch, ale tam musisz znaleźć odpowiedź.
Być może pytanie, które możesz zadać, brzmi: „Czy ten ciąg jest wynikiem kodowania ciągu Unicode w ascii?” - Na to możesz odpowiedzieć, próbując:
źródło
str
w Python 2,bytes
w Python 3).str
w dowolnym kodowaniu ISO musiałoby najpierw zostać zakodowane w Unicode. Odpowiedź powinna się w tym znaleźć.s.decode('ascii') if isinstance(s, bytes) else s.encode('ascii')
w Pythonie 3. Dane wejściowe OP to testowanie'é'
(składnia Pythona 2, Python 3 nie został w tym czasie wydany) i dlatego.decode()
jest poprawna.str
w Pythonie 2 to testowanie. Prawidłowe jest użycie,.decode('ascii')
aby dowiedzieć się, czy wszystkie bajty są w zakresie ascii.Python 3 sposób:
Aby to sprawdzić, przekaż ciąg testowy:
źródło
isascii
jest teraz funkcja, która przekazuje ciąg:isascii('somestring')
==True
iisascii('àéç')
==False
try: s.encode('ascii'); return True
except UnicodeEncodeError: return False
(jak wyżej, ale kodowanie, ponieważ w Pythonie 3 ciągi znaków są Unicode). Ta odpowiedź powoduje także błąd w Pythonie 3, gdy masz zastępcze dane (np.isascii('\uD800')
Podnosi błąd zamiast wracaćFalse
)Nowy w Python 3.7 ( bpo32677 )
Nigdy więcej męczących / nieefektywnych kontroli ascii na łańcuchach, nowa wbudowana metoda
str
/bytes
/bytearray
-.isascii()
sprawdzi, czy łańcuchy są ascii.źródło
"\x03".isascii()
jest również Prawdą. Dokumentacja mówi, że to tylko sprawdza, czy wszystkie znaki znajdują się poniżej punktu kodowego 128 (0-127). Jeśli chcesz, aby uniknąć znaki sterujące, trzeba będzie:text.isascii() and text.isprintable()
. Samo użycieisprintable
również nie jest wystarczające, ponieważ uzna, że znak taki jak ¿może być (poprawnie) nadający się do wydruku, ale nie znajduje się w sekcji do drukowania ascii, więc musisz sprawdzić oba, jeśli chcesz oba. Jeszcze jedna gotcha: spacje są uważane za drukowalne, tabulatory i znaki nowej linii nie.Wpadłem ostatnio na coś takiego - na przyszłość
którego możesz użyć z:
źródło
{'confidence': 0.99, 'encoding': 'EUC-JP'}
(co w tym przypadku było całkowicie błędne)Vincent Marchetti ma dobry pomysł, ale
str.decode
jest przestarzały w Pythonie 3. W Pythonie 3 możesz wykonać ten sam test, używającstr.encode
:Zwróć uwagę, że wyjątek, który chcesz złapać, również zmienił się z
UnicodeDecodeError
naUnicodeEncodeError
.źródło
bytes
wpisz w Pythonie 3, który nie ma.encode()
metody)..decode()
w @Vincent Marchetti odpowiedź jest poprawna .'é'
było wtedy testowaniem.Twoje pytanie jest nieprawidłowe; błąd, który widzisz, nie wynika z tego, jak zbudowałeś Pythona, ale z pomieszania ciągów bajtów i ciągów Unicode.
Ciągi bajtów (np. „Foo” lub „bar” w składni Pythona) są ciągami oktetów; numery od 0-255. Ciągi znaków Unicode (np. „Foo” lub „bar”) są ciągami punktów kodu Unicode; numery od 0-1112064. Wygląda jednak na to, że interesuje Cię znak é, który (w twoim terminalu) jest sekwencją wielobajtową reprezentującą pojedynczy znak.
Zamiast tego
ord(u'é')
spróbuj:To pokazuje, która sekwencja punktów kodowych „é” reprezentuje. Może dać ci [233] lub może dać [101, 770].
Zamiast tego
chr()
odwrócić, istniejąunichr()
:Ten znak może faktycznie być reprezentowany jako pojedynczy lub wiele „kodów” unicode, które same reprezentują grafem lub znaki. Może to być „ez ostrym akcentem (tj. Kod 233)” lub „e” (kod 101), a następnie „wyraźny akcent na poprzedni znak” (kod 770). Tak więc ten sam znak może być przedstawiony jako struktura danych Python
u'e\u0301'
lubu'\u00e9'
.Przez większość czasu nie powinieneś się tym przejmować, ale może to stanowić problem, jeśli iterujesz ciąg znaków Unicode, ponieważ iteracja działa według punktu kodowego, a nie według znaku rozkładającego się. Innymi słowy,
len(u'e\u0301') == 2
ilen(u'\u00e9') == 1
. Jeśli jest to dla Ciebie ważne, możesz przechodzić między formularzami złożonymi i rozłożonymi za pomocąunicodedata.normalize
.Glosariusz Unicode może być pomocnym przewodnikiem do zrozumienia niektórych z tych problemów, wskazując, w jaki sposób poszczególne terminy odnoszą się do różnych części reprezentacji tekstu, co jest o wiele bardziej skomplikowane, niż wielu programistów zdaje sobie sprawę.
źródło
Co powiesz na to?
źródło
Znalazłem to pytanie, próbując ustalić, jak używać / kodować / dekodować ciąg, którego kodowania nie byłem pewien (i jak uciec / przekonwertować znaki specjalne w tym ciągu).
Moim pierwszym krokiem powinno być sprawdzenie typu ciągu - nie zdawałem sobie sprawy, że mogę uzyskać dobre dane na temat jego formatowania z typów. Ta odpowiedź była bardzo pomocna i doprowadziła do prawdziwego źródła moich problemów.
Jeśli stajesz się niegrzeczny i wytrwały
szczególnie, gdy kodujesz, upewnij się, że nie próbujesz unicode () łańcucha, który już JEST unicode - z jakiegoś okropnego powodu pojawiają się błędy kodeku ascii. (Zobacz także przepis na Python Kitchen i samouczki docs Python, aby lepiej zrozumieć, jak okropne to może być.)
W końcu zdecydowałem, że to, co chciałem zrobić, to:
W debugowaniu pomocne było również ustawienie domyślnego kodowania w moim pliku na utf-8 (umieść to na początku pliku python):
Umożliwia to testowanie znaków specjalnych („àéç”) bez konieczności używania znaków ucieczki unicode (u '\ xe0 \ xe9 \ xe7').
źródło
Aby ulepszyć rozwiązanie Aleksandra z Python 2.6 (i Python 3.x), możesz użyć modułu pomocniczego curses.ascii i funkcji curses.ascii.isascii () lub różnych innych: https://docs.python.org/2.6/ biblioteka / curses.ascii.html
źródło
curses.ascii
Możesz użyć biblioteki wyrażeń regularnych, która akceptuje standardową definicję Posix [[: ASCII:]].
źródło
Żądło (
str
typ) w Pythonie to seria bajtów. Nie ma sposobu, aby po prostu spojrzeć na ciąg znaków, czy ta seria bajtów reprezentuje ciąg znaków ascii, ciąg znaków o 8-bitowym zestawie znaków, takich jak ISO-8859-1, lub ciąg znaków zakodowany za pomocą UTF-8 lub UTF-16 lub cokolwiek innego .Jeśli jednak znasz stosowane kodowanie, możesz
decode
napisać str w ciągu znaków Unicode, a następnie użyć wyrażenia regularnego (lub pętli), aby sprawdzić, czy zawiera znaki spoza zakresu, którego dotyczy.źródło
Podobnie jak odpowiedź @ RogerDahla, ale skuteczniej jest zwierać, negując klasę postaci i używając wyszukiwania zamiast
find_all
lubmatch
.Wyobrażam sobie, że wyrażenie regularne jest do tego dobrze zoptymalizowane.
źródło
Aby dołączyć pusty ciąg jako ASCII, zmienić
+
się*
.źródło
Aby zapobiec awariom kodu, możesz użyć
try-except
metody catchTypeErrors
Na przykład
źródło
try
opakowanie jest całkowicie bezcelowe. Jeśli"¶"
jest łańcuchem Unicode, toord("¶")
będzie działać, a jeśli nie jest (Python 2),for c in s
rozłoży go na bajty, więcord
będzie nadal działać.Używam następujących do ustalenia, czy ciąg jest ascii czy Unicode:
Następnie użyj bloku warunkowego, aby zdefiniować funkcję:
źródło
is_ascii(u'i am ascii')
. Mimo że litery i spacje są zdecydowanie ASCII, to wciąż zwraca,False
ponieważ wymusiliśmy, aby ciąg byłunicode
.