为什么Python字符串连接可以处理俄语文本,而String.format()不能

为什么Python字符串连接可以处理俄语文本,而String.format()不能,python,csv,character-encoding,windows-1251,Python,Csv,Character Encoding,Windows 1251,我试图解析(和转义)以字符编码存储的CSV文件的行。为了处理这种编码,我最后用这一行来测试输出,出于某种原因,这是可行的: print(row[0]+','+row[1]) 输出: Тяжелый Уборщик Обязанности,1 литр 虽然这一行行不通: print("{0},{1}".format(*row)) 输出此错误: Name,Variant Traceback (most recent call last): File "Russian.py", line

我试图解析(和转义)以字符编码存储的CSV文件的行。为了处理这种编码,我最后用这一行来测试输出,出于某种原因,这是可行的:

print(row[0]+','+row[1])
输出:

Тяжелый Уборщик Обязанности,1 литр
虽然这一行行不通:

print("{0},{1}".format(*row))
输出此错误:

Name,Variant

Traceback (most recent call last):
  File "Russian.py", line 26, in <module>
    print("{0},{1}".format(*row))
UnicodeEncodeError: 'ascii' codec can't encode characters in position 2-3: ordinal not in range(128)
如果有帮助,下面是俄语.py的完整来源:

import csv
import cgi
from chardet.universaldetector import UniversalDetector
chardet_detector = UniversalDetector()

def charset_detect(f, chunk_size=4096):
    global chardet_detector
    chardet_detector.reset()
    while 1:
        chunk = f.read(chunk_size)
        if not chunk: break
        chardet_detector.feed(chunk)
        if chardet_detector.done: break
    chardet_detector.close()
    return chardet_detector.result

with open('Russian.csv') as csv_file:
    cd_result = charset_detect(csv_file)
    encoding = cd_result['encoding']
    csv_file.seek(0)
    csv_reader = csv.reader(csv_file)
    for bytes_row in csv_reader:
        row = [x.decode(encoding) for x in bytes_row]
        if len(row) >= 6:
            #print(row[0]+','+row[1])
            print("{0},{1}".format(*row))

列表中的字符串可能已经是unicode,因此没有问题

print(row[0]+','+row[1])
Тяжелый Уборщик Обязанности,1 литр
但在这里,我们试图将unicode添加到普通字符串中!这就是为什么会出现
unicodeincodeerror

print("{0},{1}".format(*row))
因此,只需将其更改为:

print(u"{0}, {1}".format(*row))

+
操作数在
unicode
字符串和
str
字符串之间工作正常。另一方面,
str.format
不接受
unicode
字符串作为参数

因此,您可以简单地用以下内容替换有问题的行:

print(u"{0},{1}".format(*row))

这应该可以解决问题。

您正在使用
str.format()
,它隐式地将
unicode()
转换为
str()
。它必须这样做才能将值插入到提供的模板中

改用
unicode.format()

print(u"{0},{1}".format(*row))
注意格式文字前的
u
unicode.format()
必须对
str
输入进行解码,以适应最终的unicode输出

另一方面,串联可以隐式解码以生成最终的
unicode()
对象结果。如果您的
,“
值包含非ASCII字节,则隐式解码也会失败


这个故事的寓意是:在处理文本时,在代码中使用Unicode字符串文字。

,因为你很幸运。始终将文本视为Unicode,除了边缘(在摄取时解码,在生成最终输出时编码)。我的理解是,
row=[x.decode(encoding)for x in bytes_row]
正在生成Unicode字符串数组,我错了吗?
print(u{0},{1}.format(*row))
,您正试图使用str.format编码为ascii。@PadraicCunningham感谢您摧毁了我的梦想,当时我以为我得到了答案,并为自己感到骄傲@Zizouz212,这是真的,答案就像是正确的和第一。有些事情告诉我,如果你试图建立你的Python rep,Padraic Cunningham可以忍受一些偷来的答案:)这并不能真正解释为什么第一个版本可以工作。它仍在将
unicode
添加到
str
,然后将结果添加到
unicode
。解释为什么这是正确的(因为在本例中,它最终解码了
,“
)。这是错误的
str.format
不接受
unicode
字符串作为参数;它只是对它们进行编码。而
+
只有在
unicode
str
之间才能在相同意义上“正常工作”,因为它
编码
s一个或
解码
s另一个。
print(u"{0},{1}".format(*row))