Python 为什么字符串和列表在UNICODE(utf-8)中有区别?怎样才能'-';犯错误? >>final=[] >>>对于范围(65535)内的a: 最后。附加([a,chr(a)]) >>>file=open('1.txt','w',encoding='utf-8') >>>文件写入(str(最终)) 960881 >>>file.close()文件 >>>最终=“” >>>对于范围(65535)内的a: 最终+='%d------%s'(a,chr(a)) >>>file=open('2.txt','w',encoding='utf-8') >>>file.write(最终版) 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 file.write(最终版) UnicodeEncodeError:“utf-8”编解码器无法对位置873642处的字符“\ud800”进行编码:不允许使用代理

Python 为什么字符串和列表在UNICODE(utf-8)中有区别?怎样才能'-';犯错误? >>final=[] >>>对于范围(65535)内的a: 最后。附加([a,chr(a)]) >>>file=open('1.txt','w',encoding='utf-8') >>>文件写入(str(最终)) 960881 >>>file.close()文件 >>>最终=“” >>>对于范围(65535)内的a: 最终+='%d------%s'(a,chr(a)) >>>file=open('2.txt','w',encoding='utf-8') >>>file.write(最终版) 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 file.write(最终版) UnicodeEncodeError:“utf-8”编解码器无法对位置873642处的字符“\ud800”进行编码:不允许使用代理,python,unicode,Python,Unicode,如您所见,1.txt已保存。为什么保存第二个“文件”(字符串)会出错?我不知道如何将UTF-16转换为UTF-8,但是如果不要求100%的准确表示,您可能会应用此方法读取文件: >>> final=[] >>> for a in range(65535): final.append([a,chr(a)]) >>> file=open('1.txt','w',encoding='utf-8') >>> fi

如您所见,1.txt已保存。为什么保存第二个“文件”(字符串)会出错?

我不知道如何将
UTF-16
转换为
UTF-8
,但是如果不要求100%的准确表示,您可能会应用此方法读取文件:

>>> final=[]
>>> for a in range(65535):
        final.append([a,chr(a)])


>>> file=open('1.txt','w',encoding='utf-8')
>>> file.write(str(final))
960881
>>> file.close()
>>> final=''
>>> for a in range(65535):
        final+='%d -------- %s'%(a,chr(a))


>>> file=open('2.txt','w',encoding='utf-8')
>>> file.write(final)
Traceback (most recent call last):
  File "<pyshell#29>", line 1, in <module>
    file.write(final)
UnicodeEncodeError: 'utf-8' codec can't encode character '\ud800' in position 873642: surrogates not allowed

代码点
U+D800
U+DFFF
是为保留的,并且可以在错误消息中看到

UnicodeEncodeError:“utf-8”编解码器无法对位置873642处的字符“\ud800”进行编码:不允许使用代理

不能在该范围内写入字符。它仅用于UTF-16编码码点(即>65535)

请注意,Unicode是一个16位字符集,所以增加到65535是不够的。要打印所有Unicode字符,您需要一直打印到代理项范围之外的所有字符。因此,使用UTF-32也更容易:

Unicode和ISO/IEC 10646不为D800–DFFF范围内的任何代码点分配实际字符-这些代码点仅在代理项对中使用时才有意义。因此,代理项对中的单个代码点不表示字符,除非在代理项对中使用,否则无效,并且

所以我想说
chr(0xd800)
已经无效了,我猜Python只是因为速度原因没有检查它。但是UTF-8编码器确实检查了它并提出了投诉

它对第一个文件起作用的原因是,将字符串包装在一个列表中,并在该列表上使用
str
,将导致
repr
-生成字符串:

f = open(filename, encoding='utf-8', errors='replace')

请注意列表版本中的双反斜杠。它不是一个“无效字符”
\ud800
,而是六个有效字符
\
u
d
8
0
0
。这些都可以被编码。

可能是因为
\ud800
响应UTF-16代理项对导致了错误?@KarolyHorvath你是什么意思?OP正在打印无效范围内的字符。这里与UTF-16无关。无论如何,在Python中从UTF-16到UTF-8的转换是微不足道的<编码>UTF16字节。解码('utf-16')。编码('utf-8')。在这种情况下,跳过无效字符可能是一个很好的解决方法,但您甚至没有试图解释什么是错误的,或者您的解决方法是如何丢失一些数据的。@tripleee上述代码没有解决问题还是部分解决了问题?问题主要在于OP对行为的理解;你的回答并没有试图解释它,所以不,它不能解决问题;而UTF-16的“红鲱鱼”即使不是完全误导,也绝对是反复无常的。
>>> str( chr(0xd800) )
'\ud800'
>>> str([chr(0xd800)])
"['\\ud800']"