كيفية التحقق مما إذا كانت السلسلة في بايثون موجودة في ASCII؟

StackOverflow https://stackoverflow.com/questions/196345

  •  10-07-2019
  •  | 
  •  

سؤال

أريد أن أتحقق مما إذا كانت السلسلة موجودة في ASCII أم لا.

أنا على علم بذلك ord(), ولكن عندما أحاول ord('é'), ، أملك TypeError: ord() expected a character, but string of length 2 found.لقد فهمت أن سبب ذلك هو الطريقة التي بنيت بها بايثون (كما هو موضح في ord()وثائق).

هل هناك طريقة أخرى للتحقق؟

هل كانت مفيدة؟

المحلول

def is_ascii(s):
    return all(ord(c) < 128 for c in s)

نصائح أخرى

وأعتقد أنك لا تسأل السؤال الصحيح -

وسلسلة في بيثون لا يوجد لديه ممتلكات المقابلة ل"أسكي، UTF-8، أو أي ترميز آخر. مصدر سلسلة الخاص بك (سواء كنت تقرأ من ملف، والمدخلات من لوحة المفاتيح، الخ) قد يكون ترميز سلسلة يونيكود في أسكي لإنتاج سلسلة الخاص بك، ولكن هذا حيث كنت في حاجة للذهاب للإجابة.

ولعل السؤال الذي يمكن طرحه هو: "هل هذه السلسلة نتيجة لترميز سلسلة يونيكود في أسكي؟" - هذا يمكنك الإجابة     من خلال محاولة:

try:
    mystring.decode('ascii')
except UnicodeDecodeError:
    print "it was not a ascii-encoded unicode string"
else:
    print "It may have been an ascii-encoded unicode string"

وبيثون 3 الطريقة:

isascii = lambda s: len(s) == len(s.encode())

لتحقق، لتمرير سلسلة الاختبار:

str1 = "♥O◘♦♥O◘♦"
str2 = "Python"

print(isascii(str1)) -> will return False
print(isascii(str2)) -> will return True

الجديد في بايثون 3.7 ( bpo32677 )

ولا أكثر ممل / الشيكات غير فعالة أسكي على الاوتار، الجديد المدمج في str / bytes / طريقة bytearray - <وأ href = "https://docs.python.org/3/library/stdtypes.html#str.isascii "يختلط =" noreferrer "> .isascii() ومعرفة ما اذا كان سلاسل غير أسكي.

print("is this ascii?".isascii())
# True

وران إلى شيء من هذا القبيل في الآونة الأخيرة - للرجوع إليها في المستقبل

import chardet

encoding = chardet.detect(string)
if encoding['encoding'] == 'ascii':
    print 'string is in ascii'

والتي يمكن أن تستخدم مع:

string_ascii = string.decode(encoding['encoding']).encode('ascii')

سؤالك غير صحيح؛الخطأ الذي تراه ليس نتيجة لكيفية إنشاء بايثون، ولكن بسبب الخلط بين سلاسل البايت وسلاسل Unicode.

سلاسل البايت (على سبيل المثال."foo"، أو "bar"، في بناء جملة بايثون) عبارة عن تسلسلات من الثمانيات؛الأرقام من 0-255.سلاسل Unicode (على سبيل المثال.u"foo" أو u'bar') عبارة عن تسلسلات لنقاط ترميز Unicode؛الأرقام من 0-1112064.ولكن يبدو أنك مهتم بالحرف é، والذي (في جهازك الطرفي) عبارة عن تسلسل متعدد البايت يمثل حرفًا واحدًا.

بدلاً من ord(u'é'), ، جرب هذا:

>>> [ord(x) for x in u'é']

يخبرك ذلك بتسلسل نقاط الكود الذي يمثله "é".قد يعطيك [233]، أو قد يعطيك [101، 770].

بدلاً من chr() لعكس هذا، هناك unichr():

>>> unichr(233)
u'\xe9'

قد يتم تمثيل هذا الحرف في الواقع إما "نقاط رمز" مفردة أو متعددة، والتي تمثل في حد ذاتها إما حروفًا حرفية أو أحرفًا.إنها إما "e بلكنة حادة (أي نقطة الرمز 233)"، أو "e" (نقطة الرمز 101)، متبوعة بـ "لكنة حادة على الحرف السابق" (نقطة الرمز 770).لذلك يمكن تقديم هذا الحرف نفسه على أنه بنية بيانات بايثون u'e\u0301' أو u'\u00e9'.

في معظم الأوقات، لا ينبغي عليك الاهتمام بهذا الأمر، ولكن قد يصبح الأمر مشكلة إذا كنت تقوم بالتكرار عبر سلسلة Unicode، حيث يعمل التكرار حسب نقطة التعليمات البرمجية، وليس بواسطة حرف قابل للتحليل.بعبارة أخرى، len(u'e\u0301') == 2 و len(u'\u00e9') == 1.إذا كان هذا يهمك، فيمكنك التحويل بين النماذج المركبة والمتحللة باستخدام unicodedata.normalize.

معجم يونيكود يمكن أن يكون دليلاً مفيدًا لفهم بعض هذه القضايا، من خلال الإشارة إلى كيفية إشارة كل مصطلح محدد إلى جزء مختلف من تمثيل النص، وهو أمر أكثر تعقيدًا بكثير مما يدركه العديد من المبرمجين.

وماذا عن القيام بذلك؟

import string

def isAscii(s):
    for c in s:
        if c not in string.ascii_letters:
            return False
    return True

وفنسنت ماركيتي لديه فكرة الحق، ولكن تم إهمال str.decode في بيثون 3. في بيثون 3 يمكنك إجراء نفس الاختبار مع str.encode:

try:
    mystring.encode('ascii')
except UnicodeEncodeError:
    pass  # string is not ascii
else:
    pass  # string is ascii

ملحوظة باستثناء تريد تغيرت أيضا من UnicodeDecodeError إلى UnicodeEncodeError للقبض.

ولقد وجدت هذا السؤال في حين تحاول تحديد كيفية استخدام / تشفير / فك شفرة سلسلة التي لم أكن متأكدا من الترميز (وكيفية الهروب / تحويل الأحرف الخاصة في هذه السلسلة).

والخطوة الأولى بلدي كان ينبغي أن يكون للتحقق من نوع STRING- لم أكن أدرك أن هناك أتمكن من الحصول على بيانات جيدة عن تنسيقه من نوع (ق). هذا الجواب كان مفيدا للغاية، وحصلت على الجذور الحقيقية للقضايا بلدي.

إذا كنت الحصول على وقحا ومستمرة

<اقتباس فقرة>   

وUnicodeDecodeError: "أسكي" الترميز لا يمكن فك 0xc3 بايت في موقف 263: ترتيبي ليس في النطاق (128)

وخصوصا عندما كنت ENCODING، تأكد من أنك لا تحاول يونيكود () سلسلة IS بالفعل unicode- لسبب الرهيب، تحصل أخطاء أسكي الترميز. (انظر أيضا بيثون مطبخ صفة ، وفي مستندات بيثون دروس لفهم أفضل لكيفية الرهيبة هذا يمكن أن يكون)

وأخيرا قررت أن ما أردت القيام به هو هذا:

escaped_string = unicode(original_string.encode('ascii','xmlcharrefreplace'))

ومفيدة أيضا في تصحيح الأخطاء وتحديد الترميز الافتراضي في الملف الخاص بي إلى UTF-8 (وضع هذا في بداية ملف الثعبان الخاص بك):

# -*- coding: utf-8 -*-

وهذا يسمح لك لاختبار أحرف خاصة ( 'AEC') دون الحاجة إلى استخدام هروب يونيكود بها (ش '\ xe0 \ xe9 \ xe7').

>>> specials='àéç'
>>> specials.decode('latin-1').encode('ascii','xmlcharrefreplace')
'&#224;&#233;&#231;'

لتحسين الحل الكسندر من بيثون 2.6 (وفي بيثون 3.X) يمكنك استخدام المساعد وحدة curses.ascii واستخدام curses.ascii.isascii () وظيفة أو غيرها من مختلف: <لأ href = "HTTPS: // docs.python.org/2.6/library/curses.ascii.html "يختلط =" نوفولو "> https://docs.python.org/2.6/library/curses.ascii.html

from curses import ascii

def isascii(s):
    return all(ascii.isascii(c) for c in s)

هل يمكن استخدام المكتبة التعبير العادية التي يقبل POSIX معيار [[: ASCII:]]. تعريف

لدغة (str-type) في Python عبارة عن سلسلة من البايتات.هنالك مستحيل من مجرد النظر إلى السلسلة ما إذا كانت هذه السلسلة من البايتات تمثل سلسلة ascii، أو سلسلة في مجموعة أحرف 8 بت مثل ISO-8859-1 أو سلسلة مشفرة باستخدام UTF-8 أو UTF-16 أو أي شيء آخر.

ومع ذلك، إذا كنت تعرف الترميز المستخدم، فيمكنك ذلك decode قم بتحويل السلسلة str إلى سلسلة Unicode ثم استخدم تعبيرًا عاديًا (أو حلقة) للتحقق مما إذا كانت تحتوي على أحرف خارج النطاق الذي تشعر بالقلق بشأنه.

ومثل @ RogerDahl في الإجابة لكنه أكثر كفاءة لدائرة قصر بانكار الطبقة الطابع واستخدام البحث بدلا من find_all أو match.

>>> import re
>>> re.search('[^\x00-\x7F]', 'Did you catch that \x00?') is not None
False
>>> re.search('[^\x00-\x7F]', 'Did you catch that \xFF?') is not None
True

وأتصور تعبير عادي هو الأمثل جيدا لذلك.

لمنع التعليمات البرمجية من حوادث، وربما كنت ترغب في استخدام try-except للقبض TypeErrors

>>> ord("¶")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: ord() expected a character, but string of length 2 found

وعلى سبيل المثال

def is_ascii(s):
    try:
        return all(ord(c) < 128 for c in s)
    except TypeError:
        return False
import re

def is_ascii(s):
    return bool(re.match(r'[\x00-\x7F]+$', s))

لتشمل سلسلة فارغة كما ASCII، تغيير + إلى *.

وأنا استخدم ما يلي لتحديد ما إذا كانت السلسلة أسكي أو الشفرة:

>> print 'test string'.__class__.__name__
str
>>> print u'test string'.__class__.__name__
unicode
>>> 

وبعد ذلك فقط استخدام كتلة المشروط لتحديد وظيفة:

def is_ascii(input):
    if input.__class__.__name__ == "str":
        return True
    return False
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top