UnicodeDecodeError: ตัวแปลงสัญญาณ 'ascii' ไม่สามารถถอดรหัสไบต์ 0xef ในตำแหน่ง 1


106

ฉันมีปัญหาเล็กน้อยในการพยายามเข้ารหัสสตริงเป็น UTF-8 ฉันได้ลองทำสิ่งต่างๆมากมายรวมถึงการใช้string.encode('utf-8')และunicode(string)แต่ฉันได้รับข้อผิดพลาด:

UnicodeDecodeError: ตัวแปลงสัญญาณ 'ascii' ไม่สามารถถอดรหัสไบต์ 0xef ในตำแหน่ง 1: ลำดับไม่อยู่ในช่วง (128)

นี่คือสตริงของฉัน:

(。・ω・。)ノ

ฉันไม่เห็นว่ามีอะไรผิดพลาดมีความคิดอย่างไร

แก้ไข: ปัญหาคือการพิมพ์สตริงเนื่องจากแสดงไม่ถูกต้อง นอกจากนี้ข้อผิดพลาดนี้เมื่อฉันพยายามแปลง:

Python 2.7.1+ (r271:86832, Apr 11 2011, 18:13:53)
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> s = '(\xef\xbd\xa1\xef\xbd\xa5\xcf\x89\xef\xbd\xa5\xef\xbd\xa1)\xef\xbe\x89'
>>> s1 = s.decode('utf-8')
>>> print s1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 1-5: ordinal not in range(128)

มันเป็นเพียงสตริงที่แทรกตามปกติ สิ่งเดียวกันนี้เกิดขึ้นเมื่อฉันลองพิมพ์
Markum

ฉันพบสิ่งเดียวกันเมื่อติดตั้ง pip และแก้ไขจากที่นี่: [install some devel] [1] [1]: stackoverflow.com/questions/17931726/…
BollMose

คำตอบ:


70

สิ่งนี้เกี่ยวข้องกับการเข้ารหัสของเทอร์มินัลของคุณไม่ได้ตั้งค่าเป็น UTF-8 นี่คืออาคารผู้โดยสารของฉัน

$ echo $LANG
en_GB.UTF-8
$ python
Python 2.7.3 (default, Apr 20 2012, 22:39:59) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> s = '(\xef\xbd\xa1\xef\xbd\xa5\xcf\x89\xef\xbd\xa5\xef\xbd\xa1)\xef\xbe\x89'
>>> s1 = s.decode('utf-8')
>>> print s1
(。・ω・。)ノ
>>> 

ในเทอร์มินัลของฉันตัวอย่างใช้ได้กับข้างบน แต่ถ้าฉันกำจัดไฟล์ LANGตั้งค่ามันจะไม่ทำงาน

$ unset LANG
$ python
Python 2.7.3 (default, Apr 20 2012, 22:39:59) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> s = '(\xef\xbd\xa1\xef\xbd\xa5\xcf\x89\xef\xbd\xa5\xef\xbd\xa1)\xef\xbe\x89'
>>> s1 = s.decode('utf-8')
>>> print s1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 1-5: ordinal not in range(128)
>>> 

ดูเอกสารสำหรับตัวแปร linux ของคุณเพื่อค้นหาวิธีทำให้การเปลี่ยนแปลงนี้เป็นแบบถาวร


1
ตำแหน่งที่หายไปอาจเป็นสาเหตุได้เช่นกัน ในการติดตั้งให้รันsudo apt-get install language-pack-deหรือsudo locale-gen de_DE.UTF-8(สำหรับภาษาเยอรมัน)
ไม่ใช่

สำหรับฉันตัวแปรสภาพแวดล้อมที่ขาดหายไปคือLC_ALLค่าที่ง่ายที่สุดที่จะแก้ไขได้คือC.UTF-8
Robin Winslow

24

ลอง:

string.decode('utf-8')  # or:
unicode(string, 'utf-8')

แก้ไข:

'(\xef\xbd\xa1\xef\xbd\xa5\xcf\x89\xef\xbd\xa5\xef\xbd\xa1)\xef\xbe\x89'.decode('utf-8') ให้ u'(\uff61\uff65\u03c9\uff65\uff61)\uff89'ซึ่งถูกต้อง

ดังนั้นปัญหาของคุณต้องอยู่ที่สถานที่บางแห่งอาจเป็นไปได้ว่าถ้าคุณพยายามทำอะไรบางอย่างกับมันมีการแปลงโดยปริยายเกิดขึ้น (อาจเป็นการพิมพ์เขียนไปยังสตรีม ... )

หากต้องการพูดเพิ่มเติมเราจะต้องดูโค้ดบางส่วน


ทั้งสองกลับมาUnicodeEncodeError: 'charmap' codec can't encode characters in position 1-5: character maps to <undefined>
Markum

'(\xef\xbd\xa1\xef\xbd\xa5\xcf\x89\xef\xbd\xa5\xef\xbd\xa1)\xef\xbe\x89'
Markum

1
ทั้งหมดที่ฉันพยายามทำคือการพิมพ์สายเดิมในรูปแบบเดิม (´¢í´¢Ñ¤ë´¢Ñ´¢í)´¥ëแต่ฉันได้รับ
Markum

4
stringเป็น utf8 เข้ารหัส หากคุณพิมพ์มันก็แค่เปลี่ยนไบต์ไปยังเอาต์พุตสตรีมและหากเทอร์มินัลของคุณไม่ตีความเป็น utf8 คุณก็จะกลายเป็นขยะ เมื่อdecodeคุณแปลงเป็น Unicode จากนั้นคุณสามารถencodeเข้ารหัสได้อีกครั้งเพื่อให้เครื่องปลายทางของคุณเข้าใจ
mata

21

+1 ของฉันถึงความคิดเห็นของ mata ที่https://stackoverflow.com/a/10561979/1346705และการสาธิตของ Nick Craig-Wood คุณถอดรหัสสตริงได้ถูกต้อง ปัญหาเกิดจากprintคำสั่งเนื่องจากจะแปลงสตริง Unicode เป็นการเข้ารหัสคอนโซลและคอนโซลไม่สามารถแสดงสตริงได้ ลองเขียนสตริงลงในไฟล์และดูผลลัพธ์โดยใช้ตัวแก้ไขที่เหมาะสมที่รองรับ Unicode:

import codecs

s = '(\xef\xbd\xa1\xef\xbd\xa5\xcf\x89\xef\xbd\xa5\xef\xbd\xa1)\xef\xbe\x89'
s1 = s.decode('utf-8')
f = codecs.open('out.txt', 'w', encoding='utf-8')
f.write(s1)
f.close()

แล้วคุณจะเห็น(。・ω・。)ノ.


10

หากคุณกำลังทำงานบนโฮสต์ระยะไกลให้ดูที่พีซีในพื้นที่/etc/ssh/ssh_configของคุณ

เมื่อไฟล์นี้มีบรรทัด:

SendEnv LANG LC_*

แสดงความคิดเห็นโดยเพิ่ม#ที่ส่วนหัวของบรรทัด มันอาจช่วยได้

ด้วยบรรทัดนี้sshส่งตัวแปรสภาพแวดล้อมที่เกี่ยวข้องกับภาษาของพีซีของคุณไปยังโฮสต์ระยะไกล มันทำให้เกิดจำนวนมากของปัญหา


ขอบคุณ! สิ่งเหล่านี้แก้ไขปัญหาที่ฉันติดตั้งแพ็คเกจ pip ด้วย ansible และ vagrant
Maritza Esparza

10

ลองตั้งค่าการเข้ารหัสเริ่มต้นของระบบเมื่อutf-8เริ่มต้นสคริปต์เพื่อให้สตริงทั้งหมดถูกเข้ารหัสโดยใช้สิ่งนั้น

# coding: utf-8
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

ทำไมเราต้องรีโหลดในกรณีนี้?
Fallingdog

นี้ไม่ได้ทำงานในหลาม 3 อธิบายที่นี่ สำหรับฉันคำตอบของ Tsutomu ด้านล่างเป็นเคล็ดลับ
Piyush Goel

5

คุณสามารถใช้โค้ดด้านล่างที่ด้านบนของสคริปต์ของคุณตามที่Andrei Krasutskiแนะนำ

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

แต่ฉันจะแนะนำให้คุณเพิ่ม # -*- coding: utf-8 -*บรรทัดที่ด้านบนสุดของสคริปต์

basic.pyไม่ใส่มันจะพ่นด้านล่างข้อผิดพลาดในกรณีของฉันเมื่อฉันพยายามที่จะดำเนินการ

$ python basic.py
  File "01_basic.py", line 14
SyntaxError: Non-ASCII character '\xd9' in file basic.py on line 14, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

ต่อไปนี้เป็นรหัสที่แสดงbasic.pyข้อผิดพลาดด้านบน

รหัสที่มีข้อผิดพลาด

from pylatex import Document, Section, Subsection, Command, Package
from pylatex.utils import italic, NoEscape

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

def fill_document(doc):
    with doc.create(Section('ِش سثؤفهخى')):
        doc.append('إخع ساخعمي شمصشغس سحثشن فاث فقعفا')
        doc.append(italic('فشمهؤ ؤخىفثىفس شقث شمسخ ىهؤث'))

        with doc.create(Subsection('آثص ٍعلاسثؤفهخى')):
            doc.append('بشةخعس ؤقشئغ ؤاشقشؤفثقس: $&#{}')


if __name__ == '__main__':
    # Basic document
    doc = Document('basic')
    fill_document(doc)

จากนั้นฉันเพิ่ม# -*- coding: utf-8 -*-บรรทัดที่ด้านบนสุดและดำเนินการ มันได้ผล

รหัสโดยไม่มีข้อผิดพลาด

# -*- coding: utf-8 -*-
from pylatex import Document, Section, Subsection, Command, Package
from pylatex.utils import italic, NoEscape

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

def fill_document(doc):
    with doc.create(Section('ِش سثؤفهخى')):
        doc.append('إخع ساخعمي شمصشغس سحثشن فاث فقعفا')
        doc.append(italic('فشمهؤ ؤخىفثىفس شقث شمسخ ىهؤث'))

        with doc.create(Subsection('آثص ٍعلاسثؤفهخى')):
            doc.append('بشةخعس ؤقشئغ ؤاشقشؤفثقس: $&#{}')


if __name__ == '__main__':
    # Basic document
    doc = Document('basic')
    fill_document(doc)

ขอบคุณ.


1
การใช้#coding: utf-8มากกว่า# -*- coding: utf-8 -*- นี้จะง่ายต่อการจดจำ การทำงานออกจากกล่องกับงูหลามPEP 263 - งูหลามกำหนดรหัสที่มาเข้ารหัส
Andrei Krasutski

ขอบคุณสำหรับคำแนะนำ จะลองใช้ในตอนท้ายของฉันและอัปเดตในคำตอบ
hygull

4

ไม่มีปัญหากับเครื่องปลายทางของฉัน คำตอบข้างต้นช่วยให้ฉันมองไปในทิศทางที่ถูกต้อง แต่มันไม่ได้ผลสำหรับฉันจนกว่าฉันจะเพิ่ม'ignore':

fix_encoding = lambda s: s.decode('utf8', 'ignore')

ตามที่ระบุไว้ในความคิดเห็นด้านล่างสิ่งนี้อาจนำไปสู่ผลลัพธ์ที่ไม่ต้องการ OTOH มันอาจทำเคล็ดลับได้ดีพอที่จะทำให้สิ่งต่างๆทำงานได้ดีและคุณไม่สนใจว่าจะสูญเสียตัวละครบางตัวไป


2
สิ่งนี้ผิดคุณกำลังบังคับให้ฟังก์ชันแลมบ์ดาการเข้ารหัสของคุณละเว้นการเข้ารหัสซึ่งหมายความว่าคุณกำลังสูญเสียอักขระ
Maximiliano Rios

2
สิ่งนี้ช่วยแก้ปัญหาของฉันโดยที่ฉันไม่ทราบการเข้ารหัสดั้งเดิมและฉันไม่สนใจว่าจะสูญเสียอักขระบางตัว
Edhowler


1

ดูเหมือนว่าสตริงของคุณถูกเข้ารหัสutf-8แล้วปัญหาคืออะไรกันแน่? หรือกำลังพยายามทำอะไรอยู่ที่นี่ .. ?

Python 2.7.3 (default, Apr 20 2012, 22:39:59) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> s = '(\xef\xbd\xa1\xef\xbd\xa5\xcf\x89\xef\xbd\xa5\xef\xbd\xa1)\xef\xbe\x89'
>>> s1 = s.decode('utf-8')
>>> print s1
(。・ω・。)ノ
>>> s2 = u'(。・ω・。)ノ'
>>> s2 == s1
True
>>> s2
u'(\uff61\uff65\u03c9\uff65\uff61)\uff89'

การพิมพ์สตริงต้นฉบับตามที่ให้(´¢í´¢Ñ¤ë´¢Ñ´¢í)´¥ëมาฉันต้องการให้เข้ารหัสอย่างถูกต้อง
Markum

1

ในกรณีของฉันมันเกิดจากไฟล์ Unicode ของฉันถูกบันทึกด้วย "BOM" ในการแก้ปัญหานี้ฉันแตกไฟล์โดยใช้ BBEdit และทำการ "บันทึกเป็น ... " โดยเลือกการเข้ารหัส "Unicode (UTF-8)" และไม่ใช่สิ่งที่มาพร้อมกับ "Unicode (UTF-8 พร้อม BOM) "


0

ฉันได้รับข้อผิดพลาดประเภทเดียวกันและพบว่าคอนโซลไม่สามารถแสดงสตริงในภาษาอื่นได้ ดังนั้นฉันจึงทำการเปลี่ยนแปลงโค้ดด้านล่างเพื่อตั้งค่า default_charset เป็น UTF-8

data_head = [('\x81\xa1\x8fo\x89\xef\x82\xa2\x95\xdb\x8f\xd8\x90\xa7\x93x\x81\xcb3\x8c\x8e\x8cp\x91\xb1\x92\x86(\x81\x86\x81\xde\x81\x85)\x81\xa1\x8f\x89\x89\xf1\x88\xc8\x8aO\x81A\x82\xa8\x8b\xe0\x82\xcc\x90S\x94z\x82\xcd\x88\xea\x90\xd8\x95s\x97v\x81\xa1\x83}\x83b\x83v\x82\xcc\x82\xa8\x8e\x8e\x82\xb5\x95\xdb\x8c\xaf\x82\xc5\x8fo\x89\xef\x82\xa2\x8am\x92\xe8\x81\xa1', 'shift_jis')]
default_charset = 'UTF-8' #can also try 'ascii' or other unicode type
print ''.join([ unicode(lin[0], lin[1] or default_charset) for lin in data_head ])


-1

BOM มันเป็น BOM สำหรับฉันบ่อยมาก

vi ไฟล์ใช้

:set nobomb

และบันทึกไว้ เกือบตลอดเวลาที่แก้ไขได้ในกรณีของฉัน


-1

ฉันมีข้อผิดพลาดเดียวกันกับ URL ที่มีอักขระที่ไม่ใช่ ascii (ไบต์ที่มีค่า> 128)

url = url.decode('utf8').encode('utf-8')

ทำงานให้ฉันใน Python 2.7 ฉันคิดว่างานนี้เปลี่ยน 'บางอย่าง' ในการstrแสดงภายใน - นั่นคือมันบังคับให้ถอดรหัสที่ถูกต้องของลำดับไบต์ที่สำรองไว้urlและในที่สุดก็ทำให้สตริงเป็นutf-8 strพร้อมกับเวทมนตร์ทั้งหมดใน สถานที่ที่เหมาะสม Unicode ใน Python เป็นมนต์ดำสำหรับฉัน หวังว่าจะมีประโยชน์


-2

ฉันแก้ปัญหาที่เปลี่ยนในไฟล์ settings.py ด้วย 'ENGINE': 'django.db.backends.mysql' อย่าใช้ 'ENGINE': 'mysql.connector.django',


@rayryeng คุณช่วยอธิบายเหตุผลในการแก้ไขได้ไหม แต่ดูเหมือนว่ามันจะสมบูรณ์เปลี่ยนความหมายของสิ่งที่ OP เขียนจากการแนะนำการตั้งค่าโดยเฉพาะอย่างยิ่งที่จะแนะนำให้กับมัน
ไม่มีใคร

@AndrewMedico - ขอโทษด้วย ฉันเห็นว่าโพสต์นี้คล้ายกับโพสต์อื่นมากดังนั้นฉันจึงเชื่อว่ามันเหมือนกัน ฉันจะเปลี่ยนกลับ
rayryeng

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.