Saya ingin memeriksa apakah string ada di ASCII atau tidak.
Saya sadar ord()
, namun ketika saya mencoba ord('é')
, saya punya TypeError: ord() expected a character, but string of length 2 found
. Saya mengerti ini disebabkan oleh cara saya membangun Python (seperti yang dijelaskan dalam ord()
dokumentasi ).
Apakah ada cara lain untuk memeriksanya?
Jawaban:
sumber
ord(c) < 128
jauh lebih mudah dibaca dan intuitif daripadac <= "\x7F"
Saya pikir Anda tidak menanyakan pertanyaan yang tepat--
Sebuah string dalam python tidak memiliki properti yang sesuai dengan 'ascii', utf-8, atau penyandian lainnya. Sumber string Anda (apakah Anda membacanya dari file, input dari keyboard, dll.) Mungkin telah menyandikan string unicode di ascii untuk menghasilkan string Anda, tetapi di situlah Anda harus mencari jawaban.
Mungkin pertanyaan yang dapat Anda tanyakan adalah: "Apakah string ini hasil dari pengkodean string unicode di ascii?" - Ini bisa Anda jawab dengan mencoba:
sumber
str
dalam Python 2,bytes
dalam Python 3).str
dalam pengkodean ISO apa pun harus dikodekan ke Unicode terlebih dahulu. Jawabannya harus masuk ke ini.s.decode('ascii') if isinstance(s, bytes) else s.encode('ascii')
di Python 3. Input OP adalah bytestring'é'
(sintaks Python 2, Python 3 belum dirilis pada saat itu) dan oleh karena itu.decode()
sudah benar.str
pada Python 2 adalah bytestring. Itu benar untuk digunakan.decode('ascii')
untuk mengetahui apakah semua byte berada dalam kisaran ascii.Python 3 cara:
Untuk memeriksa, lewati string uji:
sumber
isascii
sekarang adalah fungsi yang Anda berikan string:isascii('somestring')
==True
danisascii('àéç')
==False
try: s.encode('ascii'); return True
except UnicodeEncodeError: return False
(Seperti di atas, tetapi penyandian, sebagai string adalah Unicode di Python 3). Jawaban ini juga menimbulkan kesalahan dalam Python 3 ketika Anda memiliki pengganti (misalnyaisascii('\uD800')
meningkatkan kesalahan alih-alih kembaliFalse
)Baru dalam Python 3.7 ( bpo32677 )
Tidak ada lagi ascii yang melelahkan / tidak efisien pada string, built-in
str
/bytes
/bytearray
metode baru -.isascii()
akan memeriksa apakah string ascii.sumber
"\x03".isascii()
Itu juga benar. Dokumentasi mengatakan ini hanya memeriksa bahwa semua karakter di bawah titik kode 128 (0-127). Jika Anda juga ingin menghindari karakter kontrol, Anda akan perlu:text.isascii() and text.isprintable()
. Hanya menggunakanisprintable
itu sendiri juga tidak cukup, karena itu akan mempertimbangkan karakter seperti ¿agar (benar) dapat dicetak, tetapi itu tidak termasuk dalam bagian ascii yang dapat dicetak, jadi Anda perlu memeriksa keduanya jika Anda menginginkan keduanya. Satu lagi gotcha: spasi dianggap dapat dicetak, tab dan baris baru tidak.Menabrak sesuatu seperti ini baru-baru ini - untuk referensi di masa mendatang
yang dapat Anda gunakan dengan:
sumber
{'confidence': 0.99, 'encoding': 'EUC-JP'}
(yang dalam hal ini benar-benar salah)Vincent Marchetti memiliki ide yang tepat, tetapi
str.decode
telah ditinggalkan dalam Python 3. Dalam Python 3 Anda dapat melakukan tes yang sama denganstr.encode
:Perhatikan pengecualian yang ingin Anda tangkap juga telah berubah dari
UnicodeDecodeError
menjadiUnicodeEncodeError
.sumber
bytes
ketik Python 3 yang tidak memiliki.encode()
metode)..decode()
dalam jawaban @Vincent Marchetti benar .'é'
apakah bytestring saat itu.Pertanyaan Anda salah; kesalahan yang Anda lihat bukan hasil dari bagaimana Anda membangun python, tetapi dari kebingungan antara string byte dan string unicode.
String byte (misalnya "foo", atau 'bar', dalam sintaks python) adalah urutan oktet; angka dari 0-255. String Unicode (mis. U "foo" atau u'bar ') adalah urutan titik kode unicode; angka dari 0-1112064. Tetapi Anda tampaknya tertarik pada karakter é, yang (di terminal Anda) adalah urutan multi-byte yang mewakili satu karakter.
Alih-alih
ord(u'é')
, coba ini:Itu memberitahu Anda urutan titik kode mana yang mewakili "é". Mungkin memberi Anda [233], atau mungkin memberi Anda [101, 770].
Alih-alih
chr()
membalikkan ini, adaunichr()
:Karakter ini sebenarnya dapat direpresentasikan sebagai satu atau beberapa "kode titik" unicode, yang dengan sendirinya mewakili grapheme atau karakter. Entah "e dengan aksen akut (yaitu, titik kode 233)", atau "e" (titik kode 101), diikuti oleh "aksen akut pada karakter sebelumnya" (titik kode 770). Jadi karakter yang sama persis ini dapat disajikan sebagai struktur data Python
u'e\u0301'
atauu'\u00e9'
.Sebagian besar waktu Anda tidak perlu peduli tentang ini, tetapi itu bisa menjadi masalah jika Anda mengulangi string unicode, karena iterasi bekerja dengan titik kode, bukan oleh karakter yang dapat diurai. Dengan kata lain,
len(u'e\u0301') == 2
danlen(u'\u00e9') == 1
. Jika ini penting bagi Anda, Anda dapat mengonversi antara formulir yang dikomposisi dan diuraikan dengan menggunakanunicodedata.normalize
.Unicode Glosarium dapat menjadi panduan bermanfaat untuk memahami beberapa masalah ini, dengan menunjukkan bagaimana masing-masing istilah spesifik merujuk pada bagian yang berbeda dari representasi teks, yang jauh lebih rumit daripada yang disadari oleh banyak programmer.
sumber
Bagaimana kalau melakukan ini?
sumber
Saya menemukan pertanyaan ini ketika mencoba menentukan bagaimana menggunakan / meng-encode / mendekodekan suatu string yang pengkodeannya tidak saya yakini (dan bagaimana cara melarikan diri / mengonversi karakter khusus dalam string itu).
Langkah pertama saya seharusnya memeriksa jenis string - saya tidak menyadari di sana saya bisa mendapatkan data yang baik tentang pemformatannya dari tipe (s). Jawaban ini sangat membantu dan sampai ke akar masalah saya yang sebenarnya.
Jika Anda bersikap kasar dan gigih
terutama ketika Anda MENYESUAIKAN, pastikan Anda tidak mencoba untuk unicode () string yang sudah IS unicode- untuk beberapa alasan yang mengerikan, Anda mendapatkan kesalahan codec ascii. (Lihat juga resep Python Kitchen , dan Python docs tutorial untuk pemahaman yang lebih baik tentang betapa buruknya hal ini.)
Akhirnya saya memutuskan bahwa yang ingin saya lakukan adalah ini:
Juga membantu dalam debugging adalah menetapkan pengkodean default di file saya ke utf-8 (letakkan ini di awal file python Anda):
Itu memungkinkan Anda untuk menguji karakter khusus ('àéç') tanpa harus menggunakan kode unicode escapes (u '\ xe0 \ xe9 \ xe7').
sumber
Untuk meningkatkan solusi Alexander dari Python 2.6 (dan dalam Python 3.x) Anda dapat menggunakan modul helper.ascii dan gunakan fungsi curses.ascii.isascii () atau berbagai fungsi lainnya: https://docs.python.org/2.6/ library / curses.ascii.html
sumber
curses.ascii
Anda bisa menggunakan pustaka ekspresi reguler yang menerima definisi standar Posix [[: ASCII:]].
sumber
Sengatan (
str
-type) dalam Python adalah serangkaian byte. Tidak ada cara untuk mengatakan hanya dari melihat string apakah rangkaian byte ini mewakili string ascii, string dalam charset 8-bit seperti ISO-8859-1 atau string yang dikodekan dengan UTF-8 atau UTF-16 atau apa pun. .Namun, jika Anda tahu penyandian yang digunakan, maka Anda dapat
decode
memasukkan str ke string unicode dan kemudian menggunakan ekspresi reguler (atau loop) untuk memeriksa apakah itu berisi karakter di luar rentang yang Anda khawatirkan.sumber
Seperti jawaban @ RogerDahl tetapi lebih efisien untuk hubungan pendek dengan meniadakan kelas karakter dan menggunakan pencarian daripada
find_all
ataumatch
.Saya membayangkan ungkapan reguler dioptimalkan dengan baik untuk ini.
sumber
Untuk memasukkan string kosong sebagai ASCII, ubah
+
ke*
.sumber
Untuk mencegah kode Anda mogok, Anda mungkin ingin menggunakan
try-except
untuk menangkapTypeErrors
Sebagai contoh
sumber
try
wrapper benar-benar sia-sia. Jika"¶"
string Unicode, makaord("¶")
akan berfungsi, dan jika bukan (Python 2),for c in s
akan menguraikannya menjadi byte sehinggaord
akan terus bekerja.Saya menggunakan berikut ini untuk menentukan apakah string ascii atau unicode:
Kemudian gunakan saja blok kondisional untuk mendefinisikan fungsi:
sumber
is_ascii(u'i am ascii')
. Meskipun huruf dan spasi jelas ASCII, ini masih kembaliFalse
karena kami memaksakan stringunicode
.