"خطأ في UnicodeEncodeError:برنامج الترميز "ascii" لا يمكنه تشفير الأحرف"

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

سؤال

أحاول تمرير سلاسل كبيرة من لغة HTML العشوائية من خلال التعبيرات العادية ويختنق البرنامج النصي Python 2.6 الخاص بي على هذا:

خطأ في ترميز Unicode:لا يستطيع برنامج الترميز "ascii" تشفير الأحرف

لقد تتبعته مرة أخرى إلى علامة تجارية مرتفعة في نهاية هذه الكلمة:الحماية™ - وأتوقع أن أواجه آخرين مثلها في المستقبل.

هل هناك وحدة لمعالجة الأحرف غير ascii؟أو ما هي أفضل طريقة للتعامل/الهروب من الأشياء غير ascii في بيثون؟

شكرًا!الخطأ الكامل:

E
======================================================================
ERROR: test_untitled (__main__.Untitled)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Python26\Test2.py", line 26, in test_untitled
    ofile.write(Whois + '\n')
UnicodeEncodeError: 'ascii' codec can't encode character u'\u2122' in position 1005: ordinal not in range(128)

البرنامج النصي الكامل:

from selenium import selenium
import unittest, time, re, csv, logging

class Untitled(unittest.TestCase):
    def setUp(self):
        self.verificationErrors = []
        self.selenium = selenium("localhost", 4444, "*firefox", "http://www.BaseDomain.com/")
        self.selenium.start()
        self.selenium.set_timeout("90000")

    def test_untitled(self):
        sel = self.selenium
        spamReader = csv.reader(open('SubDomainList.csv', 'rb'))
        for row in spamReader:
            sel.open(row[0])
            time.sleep(10)
            Test = sel.get_text("//html/body/div/table/tbody/tr/td/form/div/table/tbody/tr[7]/td")
            Test = Test.replace(",","")
            Test = Test.replace("\n", "")
            ofile = open('TestOut.csv', 'ab')
            ofile.write(Test + '\n')
            ofile.close()

    def tearDown(self):
        self.selenium.stop()
        self.assertEqual([], self.verificationErrors)

if __name__ == "__main__":
    unittest.main()
هل كانت مفيدة؟

المحلول

أنت تحاول تمرير سلسلة بايت إلى شيء ما، لكن من المستحيل (بسبب ندرة المعلومات التي تقدمها) معرفة ذلك ماذا الذي تحاول تمريره إليه.عليك أن تبدأ بسلسلة Unicode لا يمكن تشفيرها كـ ASCII (برنامج الترميز الافتراضي)، لذلك، سيتعين عليك التشفير باستخدام برنامج ترميز مختلف (أو ترجمته بحروف صوتية، كما يقترح @R.Pate) - ولكن من المستحيل استخدامه لـ يقول ماذا برنامج الترميز الذي يجب عليك استخدامه، لأننا لا نعرف ما الذي تقوم بتمريره عبر سلسلة بايت، وبالتالي لا نعرف ما الذي سيتمكن هذا النظام الفرعي غير المعروف من قبوله ومعالجته بشكل صحيح فيما يتعلق ببرامج الترميز.

في مثل هذا الظلام الدامس كما تركتنا فيه، utf-8 هو تخمين أعمى معقول (نظرًا لأنه برنامج ترميز يمكن أن يمثل أي سلسلة Unicode تمامًا كسلسلة بايت، وهو برنامج الترميز القياسي للعديد من الأغراض، مثل XML) - ولكن لا يمكن أن يكون أكثر من مجرد تخمين أعمى، حتى وما لم تكن ستخبرنا المزيد عنه ماذا الذي تحاول تمرير تلك السلسلة الثانوية إليه ولأي غرض.

تمرير thestring.encode('utf-8') بدلا من العارية thestring سيؤدي بالتأكيد إلى تجنب الخطأ المحدد الذي تراه الآن، ولكنه قد يؤدي إلى شاشات عرض غريبة (أو أي شيء آخر يكون ما تحاول القيام به مع هذا الاختبار!) ما لم يكن المستلم جاهزًا وراغبًا وقادرًا على قبول ترميز utf-8 (وكيف يمكننا أن نعرف، وليس لدينا أي فكرة على الإطلاق عما يمكن أن يكون عليه المستلم؟!-)

نصائح أخرى

وكنت في محاولة لتحويل يونيكود الى أسكي في وضع "الصارم":

>>> help(str.encode)
Help on method_descriptor:

encode(...)
    S.encode([encoding[,errors]]) -> object

    Encodes S using the codec registered for encoding. encoding defaults
    to the default encoding. errors may be given to set a different error
    handling scheme. Default is 'strict' meaning that encoding errors raise
    a UnicodeEncodeError. Other possible values are 'ignore', 'replace' and
    'xmlcharrefreplace' as well as any other name registered with
    codecs.register_error that is able to handle UnicodeEncodeErrors.

وربما كنت تريد شيئا مثل واحد مما يلي:

s = u'Protection™'

print s.encode('ascii', 'ignore')    # removes the ™
print s.encode('ascii', 'replace')   # replaces with ?
print s.encode('ascii','xmlcharrefreplace') # turn into xml entities
print s.encode('ascii', 'strict')    # throw UnicodeEncodeErrors

والطريقة "أفضل" يعتمد دائما على الاحتياجات الخاصة بك. الأمر كذلك، فما هي لك؟ تتجاهل غير ASCII-مناسبة؟ يجب استبدال ™ مع "(TM)"؟ (الذي يبدو يتوهم لهذا المثال، ولكن سرعان ما ينهار لأخرى codepoints ولكن قد يكون مجرد ما تريد.) هل يمكن أن يكون استثناء بالضبط ما تحتاج إليه؛ الآن تحتاج فقط إلى التعامل معها بطريقة ما؟

وفقط يمكنك الإجابة على هذا السؤال حقا.

وأولا وقبل كل شيء، حاول تثبيت ترجمة للغة الإنجليزية (أو أي دولة أخرى إذا لزم الأمر):

sudo apt-get install language-pack-en

والذي يوفر تحديثات البيانات الترجمة لجميع الباقات المدعومة (بما في ذلك بيثون).

وتأكد من استخدام الترميز الصحيح في التعليمات البرمجية.

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

open(foo, encoding='utf-8')

وثم مضاعفة التحقق من تكوين النظام الخاص بك مثل قيمة LANG أو تكوين لغة (/etc/default/locale) و لا تنسى لإعادة الدخول الدورة الخاصة بك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top