如何重现 UnicodeEncodeError?

How to reproduce UnicodeEncodeError?

我在生产系统中遇到错误,但无法在开发环境中重现:

with io.open(file_name, 'wt') as fd:
    fd.write(data)

异常:

  File "/home/.../foo.py", line 18, in foo
    fd.write(data)

UnicodeEncodeError: 'ascii' codec can't encode character u'\xe4' in position 6400: ordinal not in range(128)

我已经试过了,但是很多奇怪的字符变成了变量data

但到现在为止我无法重现 UnicodeEncodeError

data 中需要什么才能获得 UnicodeEncodeError

更新

python -c 'import locale; print locale.getpreferredencoding()'
UTF-8

更新2

如果我通过 shell 和网络请求调用 locale.getpreferredencoding(),则编码为 "UTF-8"。

我在我的代码中更新了我的异常处理并记录了几天后的 getpreferredencoding()。现在又出现了(到现在我还无法强制或重现),编码是"ANSI_X3.4-1968"!

我不知道这个编码是在哪里设置的....

这使我的问题转向了不同的方向。留下这个问题没有用。我现在的问题是:首选编码在哪里更改?但这不是这个问题的一部分。

非常感谢所有

您依赖平台的默认编码;当默认编码不支持您写入文件的 Unicode 字符时,您会遇到编码异常。

来自io.open() documentation

encoding is the name of the encoding used to decode or encode the file. This should only be used in text mode. The default encoding is platform dependent (whatever locale.getpreferredencoding() returns), but any encoding supported by Python can be used.

对于您的具体情况,locale.getpreferredencoding() 返回的默认值是 ASCII,因此 ASCII 范围之外的任何 Unicode 字符都会导致此问题,U-0080 及更高版本。

请注意,语言环境取自您的环境;如果它是 ASCII,这通常意味着语言环境设置为 POSIX default locale, C.

明确指定编码:

with io.open(file_name, 'wt', encoding='utf8') as fd:
    fd.write(data)

我以UTF-8为例;您选择什么完全取决于您的用例和您要写出的数据。

将您的 write 包装在 try/except 中并将数据保存到二进制文件中——您将能够准确地看到哪些数据给您带来了问题:

with io.open(file_name, 'wt') as fd:
    try:
        fd.write(data)
    except UnicodeEncodeError:
        with open('/path/to/save/error.bin', 'wb') as err:
            err.write(data)
        raise

我试过这个来重现错误:

with open(filename, 'wt', encoding='ascii') as fd:
    fd.write('\xa0')

Traceback (most recent call last):
File "test.py", line 2, in fd.write('\xa0')
UnicodeEncodeError: 'ascii' codec can't encode character '\xa0' in position 0: ordinal not in range(128)