为什么我的Python程序在IntelliJ中得到UnicodeDecodeError但是从命令行可以正常?

时间:2012-09-13 15:01:00

标签: python json encoding intellij-idea

我有一个简单的程序,可以加载一个包含有趣角色的.json文件。程序(见下文)在终端中运行良好但在IntelliJ中出现此错误:

  

UnicodeDecodeError:'ascii'编解码器无法将字节0xe2解码到位   2:序数不在范围内(128)

关键代码是:

with open(jsonFileName) as f:
    jsonData = json.load(f)

如果我用以下代码替换open:

with open(jsonFileName, encoding='utf-8') as f:

然后它可以在IntelliJ和终端中工作。我还是Python和IntelliJ插件的新手,我不明白他们为什么会有所不同。我认为sys.path可能会有所不同,但输出让我觉得这不是原因。有人可以解释一下吗?谢谢!

版本:

  • OS:Mac OS X 10.7.4(也在10.6.8上测试)
  • Python 3.2.3(v3.2.3:3d0686d90f55,2012年4月10日,11:25:50)/Library/Frameworks/Python.framework/Versions/3.2/bin/python3.2
  • IntelliJ:11.1.3 Ultimate

文件(2):

1。 unicode-error-demo.py

#!/usr/bin/python

import json
from pprint import pprint as pp
import sys

def main():
    if len(sys.argv) is not 2:
        print(sys.argv[0], "takes one arg: a .json file")
        return

    jsonFileName = sys.argv[1]
    print("sys.path:")
    pp(sys.path)
    print("processing", jsonFileName)

#    with open(jsonFileName) as f:           # OK in Terminal, but BUG in IntelliJ: UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 2: ordinal not in range(128)
    with open(jsonFileName, encoding='utf-8') as f:     # OK in both
        jsonData = json.load(f)
        pp(jsonData)


if __name__ == "__main__":
    main()

2。编码 - temp.json

["™"]

2 个答案:

答案 0 :(得分:4)

JSON .load()函数需要Unicode数据,而不是原始字节。 Python会自动尝试使用默认编解码器(在您的情况下为ASCII)将字节字符串解码为Unicode字符串,并且失败。通过使用UTF-8编解码器打开文件,Python会为您进行显式转换。请参阅open() function,其中说明:

  

在文本模式下,如果未指定编码,则使用的编码取决于平台。

将使用的编码确定如下:

这一切都是在C中完成的,但它的python等价物是:

if encoding is None:
    encoding = os.device_encoding()
if encoding is None:
    encoding = locale.getpreferredencoding(False)
if encoding is None:
    encoding = 'ASCII'

因此,当您在终端中运行程序时,os.deviceencoding()会返回'UTF-8',但在IntelliJ下运行时没有终端,如果没有设置语言环境,则python使用'ASCII'

Python Unicode HOWTO告诉你所有关于unicode字符串和bytestrings以及编码之间的区别。关于这个主题的另一篇必要文章是Joel Spolsky的Absolute Minimum Unicode knowledge article

答案 1 :(得分:0)

Python 2.x有字符串和unicode字符串。基本字符串使用ASCII编码。 ASCII仅使用7位/字符,允许编码128个字符,而现代UTF-8使用最多4个字节/字符。 UTF-8与ASCII兼容(因此任何ASCII编码的字符串都是有效的UTF-8字符串),但不是相反。

显然,您的文件名包含非ASCII字符。并且默认情况下python想要以简单的ASCII编码字符串读取它,发现非ASCII字符(它的第一个位不是0,因为它是0xe2)并且说'ascii'编解码器不能解码位置2中的字节0xe2:序数不在范围内(128)。

与python无关,但仍然是我最喜欢的关于编码的教程:

http://hektor.umcs.lublin.pl/~mikosmul/computing/articles/linux-unicode.html