Python Unicode编码

Python Unicode编码,python,unicode,encode,argparse,Python,Unicode,Encode,Argparse,我正在使用argparse读取python代码的参数。其中一个输入是文件的标题[title],它可以包含Unicode字符。我一直在使用22少女時代22作为测试字符串 我需要将输入值title写入文件,但当我尝试将字符串转换为UTF-8时,它总是抛出一个错误: UnicodeDecodeError:“ascii”编解码器无法解码位置2:序号中的字节0x8f 不在范围内(128) 我一直在四处寻找,我需要我的字符串以u“foo”的形式调用.encode() 当我从argparse对输入运行type

我正在使用
argparse
读取python代码的参数。其中一个输入是文件的标题[
title
],它可以包含Unicode字符。我一直在使用
22少女時代22作为测试字符串

我需要将输入值
title
写入文件,但当我尝试将字符串转换为
UTF-8
时,它总是抛出一个错误:

UnicodeDecodeError:“ascii”编解码器无法解码位置2:序号中的字节0x8f 不在范围内(128)

我一直在四处寻找,我需要我的字符串以
u“foo”
的形式调用
.encode()

当我从
argparse
对输入运行
type()
时,我看到:

<type 'str'>
这种方法根本不起作用。想法

编辑1:

一些示例代码,其中
title
22少女時代22

inputs = vars(parser.parse_args())
title = inputs["title"]
print type(title)
print type(u'foo')
title = title.encode('utf8') # This line throws the error
print title

所以,这对我来说确实有效:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument(u'title', metavar='T', type=str, help='this will be unicode encoded.')
opts = parser.parse_args()
print opts.title.decode('utf8')

我的终端模拟器(OS X terminal.app)使用UTF-8。如果您的终端未配置为UTF-8操作,那么它将无法工作(这是一个终端问题,而不是Python问题)。

看起来您的输入数据是(日语的传统编码),它在bytestring中的位置2处生成字节0x8f:

>>> '22少女時代22'.encode('sjis')
b'22\x8f\xad\x8f\x97\x8e\x9e\x91\xe322'
(在Python 3提示下)

现在,我猜为了“将字符串转换为UTF-8”,您使用了

title.encode('utf8')
问题在于
title
实际上是一个包含SJIS编码字符串的ByTestString。由于Python 2中的一个设计缺陷,bytestring可以直接
encode
d,并且它假定bytestring是ASCII编码的。所以你所拥有的在概念上等同于

title.decode('ascii').encode('utf8')
当然,
decode
调用失败

在编码为UTF-8之前,您应该将SJIS显式解码为Unicode字符串:

title.decode('sjis').encode('utf8')

正如Mark Tolonen指出的,您可能正在控制台中键入字符,而您的控制台编码是非Unicode编码

因此,您的
sys.stdin.encoding
is是微软的SJIS变体。为此,请使用

title.decode('cp932').encode('utf8')

您确实应该将控制台编码设置为标准UTF-8,但我不确定这在Windows上是否可行。如果这样做,您可以跳过解码/编码步骤,只需通过testring将输入写入文件。

设置
type=unicode
就像使用
unicode(arg)
在Python 2.X上默认使用
ascii
进行解码。如果从控制台运行,
sys.stdin.encoding
是用于输入的编码,如下所示:

inputs = vars(parser.parse_args())
title = inputs["title"]
print type(title)
print type(u'foo')
title = title.decode(sys.stdin.encoding)
print title
无论Windows上的编码是什么,都应该使用
mbcs
编码,它表示非Unicode Windows程序使用的当前编码。这似乎就是
argparse
所使用的,因为I
sys.stdin.encoding
是OEM控制台编码,它并不总是与Windows编码相同。在美国Windows上,
cp437
是控制台OEM编码,
cp1252
是Windows编码:

import argparse
import codecs
parser = argparse.ArgumentParser()
parser.add_argument(u'title', metavar='T', type=str, help='this will be unicode encoded.')
opts = parser.parse_args()
title = opts.title.decode('mbcs')
with codecs.open('out.txt','w',encoding='utf-8-sig') as f:
    f.write(title)
out.txt
应在记事本中显示原始输入


utf-8-sig
编码在utf-8文件的开头写入Windows喜欢的所谓字节顺序标记(byte order mark,BOM)
utf-8
可以在不需要的情况下使用,但记事本喜欢它。

您的输入数据是什么编码?@MarkTolonen好的,我会编辑我的帖子。OP可以执行
import sys;在控制台上打印sys.stdin.encoding
以确定输入编码,或者只使用
title.decode(sys.stdin.encoding)
。在Python 2.7.2上,我从
print sys.stdin.encoding接收到
cp932
@Mechanicalsnail-Hmm.调用
打印标题。解码('cp932')。编码('utf8')
打印
22蟆大・ウ譎ゆサ」22这是输入字符串的奇数突变。想法?终端是cp932,因此无法正确显示UTF-8。要查看它,您需要将编码字符串写入文件,并在支持UTF-8的查看器中读取。@Morrowind789:该文件的输出是UTF-8编码的。该语句将其写入CP932编码的控制台,因此将其解释为CP932,从而产生mojibake。特别是,这与您的输出(Python3控制台)相匹配:
'22少女時代22.编码('utf8')。解码('cp932')
'22蟆大・ウ譎ゆサ」22'
Hmm很有趣。让我重新检查一下我的环境。我使用的是2.7.2。很好,你可以使用
title.decode(sys.stdin.encoding)
@Mechanicalsnail,但它在美国的Windows上不起作用。我补充了一条说明原因。某些Windows系统对控制台和非控制台程序的编码不同。@MarkTolonen我可以确认这在运行Win7 x64的机器上有效。
inputs = vars(parser.parse_args())
title = inputs["title"]
print type(title)
print type(u'foo')
title = title.decode(sys.stdin.encoding)
print title
import argparse
import codecs
parser = argparse.ArgumentParser()
parser.add_argument(u'title', metavar='T', type=str, help='this will be unicode encoded.')
opts = parser.parse_args()
title = opts.title.decode('mbcs')
with codecs.open('out.txt','w',encoding='utf-8-sig') as f:
    f.write(title)