locale.getpreferredencoding() - 为什么重置string.letters?

Ant*_*ile 17 python

>>> import string
>>> import locale
>>> string.letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> locale.getpreferredencoding()
'UTF-8'
>>> string.letters
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
Run Code Online (Sandbox Code Playgroud)

有没有解决方法呢?

平台:Linux Python2.6.7和Python2.7.3似乎受到影响,在Python3中运行良好(带ascii_letters)

Ben*_*aum 15

注意:OP解决问题的方法是转移encoding='UTF-8'open呼叫.如果你遇到这个问题并且只是寻找修复,这是有效的.帖子的其余部分强调了为什么.


怎么了

正如卢卡斯所说,文件规定:

在某些系统上,必须调用setlocale()来获取用户首选项

最初,string.letters设置为返回lowercase + uppercase:

lowercase = 'abcdefghijklmnopqrstuvwxyz'
uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
letters = lowercase + uppercase
Run Code Online (Sandbox Code Playgroud)

但是,当您调用时getpreferredencoding(),_locale模块会PyDict_SetItemString(string, "letters", ulo);fixup_ulcase(void)使用以下内容生成它们之后通过调用来覆盖它:

/* create letters string */
n = 0;
for (c = 0; c < 256; c++) {
    if (isalpha(c))
        ul[n++] = c;
}
ulo = PyString_FromStringAndSize((const char *)ul, n);
if (!ulo)
    return;
if (string)
    PyDict_SetItemString(string, "letters", ulo);
Py_DECREF(ulo);
Run Code Online (Sandbox Code Playgroud)

反过来,这被称为PyLocale_setlocale确实setlocale,这被称为getpreferredencoding- 代码http://hg.python.org/cpython/file/07a6fca7ff42/Lib/locale.py#l612:

  def getpreferredencoding(do_setlocale = True):
        """Return the charset that the user is likely using,
        according to the system configuration."""
        if do_setlocale:
            oldloc = setlocale(LC_CTYPE)
            try:
                setlocale(LC_CTYPE, "")
            except Error:
                pass
            result = nl_langinfo(CODESET)
            setlocale(LC_CTYPE, oldloc)
            return result
        else:
            return nl_langinfo(CODESET)
Run Code Online (Sandbox Code Playgroud)

我该如何避免呢?

尝试 getpreferredencoding(False)

为什么它不会发生在Windows中?

Windows使用不同的代码来获取区域设置,如此处所示.

在Python 3中

在Python 3中,getdefaultlocale不接受布尔setlocale变量,并且不会调用setlocale本身,如此处所示.