كيف أتحقق مما إذا كانت السلسلة هي Unicode أم ascii؟

سئل على ١٣ فبراير ٢٠١١  ·  تمت مشاهدة 362.2k مرة  ·  مصدر

TIMEX picture
في ١٣ فبراير ٢٠١١

ماذا علي أن أفعل في بايثون لمعرفة أي ترميز يحتوي على سلسلة؟

الإجابات

Greg Hewgill picture
في ١٣ فبراير ٢٠١١
303

في Python 3 ، جميع السلاسل عبارة عن سلاسل من أحرف Unicode. يوجد نوع bytes يحتوي على بايت خام.

في Python 2 ، قد تكون السلسلة من النوع str أو من النوع unicode . يمكنك معرفة أي رمز يستخدم شيئًا مثل هذا:

def whatisthis(s):
    if isinstance(s, str):
        print "ordinary string"
    elif isinstance(s, unicode):
        print "unicode string"
    else:
        print "not a string"

هذا لا يميز "Unicode أو ASCII" ؛ إنه يميز فقط أنواع بايثون. قد تتكون سلسلة Unicode من أحرف بحتة في نطاق ASCII ، وقد تحتوي سلسلة البايت على ASCII أو Unicode المشفر أو حتى بيانات غير نصية.

Mikel picture
في ١٣ فبراير ٢٠١١
125

كيفية معرفة ما إذا كان الكائن عبارة عن سلسلة Unicode أم سلسلة بايت

يمكنك استخدام type أو isinstance .

في Python 2:

>>> type(u'abc')  # Python 2 unicode string literal
<type 'unicode'>
>>> type('abc')   # Python 2 byte string literal
<type 'str'>

في Python 2 ، str هو مجرد سلسلة من البايتات. بايثون لا تعرف ما هو ترميزها. النوع unicode هو الطريقة الأكثر أمانًا لتخزين النص. إذا كنت تريد أن تفهم هذا أكثر ، فإنني أوصي بـ http://farmdev.com/talks/unicode/ .

في Python 3:

>>> type('abc')   # Python 3 unicode string literal
<class 'str'>
>>> type(b'abc')  # Python 3 byte string literal
<class 'bytes'>

في Python 3 ، يكون str مثل Python 2 unicode ، ويستخدم لتخزين النص. ما كان يسمى str في Python 2 يسمى bytes في Python 3.


كيفية معرفة ما إذا كانت سلسلة البايت صالحة utf-8 أو ascii

يمكنك الاتصال بـ decode . إذا أثار استثناء UnicodeDecodeError ، فهذا يعني أنه غير صالح.

>>> 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)
ThinkBonobo picture
في ٩ سبتمبر ٢٠١٣
46

في python 3.x ، تكون جميع السلاسل متوالية من أحرف Unicode. وإجراء فحص isinstance لـ str (وهو ما يعني سلسلة unicode افتراضيًا) يجب أن يكون كافياً.

isinstance(x, str)

فيما يتعلق بـ python 2.x ، يبدو أن معظم الأشخاص يستخدمون عبارة if التي تحتوي على فحصين. واحد لشريط وواحد لليونيكود.

إذا كنت تريد التحقق مما إذا كان لديك كائن "يشبه السلسلة" مع جملة واحدة ، فيمكنك القيام بما يلي:

isinstance(x, basestring)
Alex Dean picture
في ٢١ مايو ٢٠١٢
32

Unicode ليس ترميزًا - على حد تعبير كومار ماكميلان:

إذا كانت سلاسل ASCII و UTF-8 وسلاسل البايت الأخرى "نص" ...

... ثم Unicode هو "text-ness" ؛

إنه الشكل المجرد للنص

احصل على قراءة لـ McMillan Unicode في Python ، حديث مبسوم

Dave Burton picture
في ١٤ أغسطس ٢٠١٢
23

إذا كانت التعليمات البرمجية الخاصة بك بحاجة إلى أن تكون متوافقة مع كل من Python 2 و Python 3 ، فلا يمكنك استخدام أشياء مثل isinstance(s,bytes) أو isinstance(s,unicode) دون تغليفها في تجربة / باستثناء أو اختبار إصدار Python ، لأن bytes غير معرّف في Python 2 و unicode غير معرّف في Python 3.

هناك بعض الحلول القبيحة. القبيح للغاية هو مقارنة اسم النوع ، بدلاً من مقارنة النوع نفسه. هذا مثال:

# convert bytes (python 3) or unicode (python 2) to str
if 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)

يمكن القول إن الحل البديل الأقل قبحًا هو التحقق من رقم إصدار Python ، على سبيل المثال:

if sys.version_info >= (3,0,0):
    # for Python 3
    if isinstance(s, bytes):
        s = s.decode('ascii')  # or  s = str(s)[2:-1]
else:
    # for Python 2
    if isinstance(s, unicode):
        s = str(s)

كلاهما غير أسطوري ، وفي معظم الأحيان هناك طريقة أفضل.

madjardi picture
في ٨ أغسطس ٢٠١٦
12

استعمال:

import six
if isinstance(obj, six.text_type)

داخل المكتبة الست تتمثل في:

if PY3:
    string_types = str,
else:
    string_types = basestring,
Veedrac picture
في ٩ يوليو ٢٠١٤
4

لاحظ أنه في Python 3 ، ليس من العدل حقًا قول أي مما يلي:

  • str s هي UTFx لأي x (مثل UTF8)

  • str s هي Unicode

  • str s عبارة عن مجموعات مرتبة من أحرف Unicode

نوع Python str هو (عادة) سلسلة من نقاط كود Unicode ، بعضها يرتبط بالأحرف.


حتى في Python 3 ، ليس من السهل الإجابة على هذا السؤال كما قد تتخيل.

تتمثل إحدى الطرق الواضحة لاختبار السلاسل المتوافقة مع ASCII في محاولة تشفير:

"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)

الخطأ يميز الحالات.

في Python 3 ، توجد بعض السلاسل التي تحتوي على نقاط كود 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

يتم استخدام نفس الطريقة للتمييز بينهما.

jfl picture
في ٢٣ ديسمبر ٢٠١٥
3

قد يساعد هذا شخصًا آخر ، لقد بدأت في اختبار نوع سلسلة المتغير s ، ولكن بالنسبة لتطبيقي ، كان من المنطقي أكثر ببساطة إرجاع s كـ utf-8. العملية التي تستدعي return_utf تعرف ما الذي تتعامل معه وتستطيع التعامل مع السلسلة بشكل مناسب. الكود ليس أصليًا ، لكنني أنوي أن يكون إصدار Python محايدًا دون اختبار إصدار أو استيراد ستة. الرجاء التعليق مع إدخال تحسينات على نموذج التعليمات البرمجية أدناه لمساعدة الآخرين.

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')
    except TypeError:
        try:
            return str(s).encode('utf-8')
        except AttributeError:
            return s
    except AttributeError:
        return s
    return s # assume it was already utf-8
Seb picture
في ١٣ فبراير ٢٠١١
2

يمكنك استخدام Universal Encoding Detector ، ولكن كن على علم بأنه سيعطيك أفضل تخمين ، وليس الترميز الفعلي ، لأنه من المستحيل معرفة ترميز سلسلة "abc" على سبيل المثال. سوف تحتاج إلى الحصول على معلومات الترميز في مكان آخر ، على سبيل المثال يستخدم بروتوكول HTTP رأس نوع المحتوى لذلك.

Vishvajit Pathak picture
في ٢٨ مايو ٢٠١٨
0

من أجل التوافق py2 / py3 ، استخدم ببساطة ملفات

import six if isinstance(obj, six.text_type)