Eri*_*got 146
这是一个更简单的方法(hack),它返回setdefaultencoding()从sys以下位置删除的函数:
import sys
# sys.setdefaultencoding() does not exist, here!
reload(sys) # Reload does the trick!
sys.setdefaultencoding('UTF8')
Run Code Online (Sandbox Code Playgroud)
但这不是一件安全的事情:这显然是一个黑客,因为在Python启动时sys.setdefaultencoding()故意将其删除sys.重新启用它并更改默认编码可能会破坏依赖于ASCII的默认代码(此代码可以是第三方,这通常会使修复它变得不可能或危险).
ima*_*man 63
如果在尝试管道/重定向脚本输出时出现此错误
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)
只需在控制台中导出PYTHONIOENCODING,然后运行您的代码.
export PYTHONIOENCODING=utf8
luk*_*mdo 51
A)控制sys.getdefaultencoding()输出:
python -c 'import sys; print(sys.getdefaultencoding())'
Run Code Online (Sandbox Code Playgroud)
ascii
然后
echo "import sys; sys.setdefaultencoding('utf-16-be')" > sitecustomize.py
Run Code Online (Sandbox Code Playgroud)
和
PYTHONPATH=".:$PYTHONPATH" python -c 'import sys; print(sys.getdefaultencoding())'
Run Code Online (Sandbox Code Playgroud)
utf-16-be
你可以将你的sitecustomize.py放在更高的位置PYTHONPATH.
您也可以尝试reload(sys).setdefaultencoding@EOL
B)要控制stdin.encoding并且stdout.encoding您想要设置PYTHONIOENCODING:
python -c 'import sys; print(sys.stdin.encoding, sys.stdout.encoding)'
Run Code Online (Sandbox Code Playgroud)
ascii ascii
然后
PYTHONIOENCODING="utf-16-be" python -c 'import sys;
print(sys.stdin.encoding, sys.stdout.encoding)'
Run Code Online (Sandbox Code Playgroud)
utf-16-be utf-16-be
最后:您可以使用A)或B)或两者兼而有之!
Chr*_*heD 17
从PyDev 3.4.1 开始,默认编码不再被更改.有关详细信息,请参阅此票
对于早期版本,解决方案是确保PyDev不以UTF-8作为默认编码运行.在Eclipse下,运行对话框设置("运行配置",如果我没记错的话); 您可以在常用选项卡上选择默认编码.如果您希望"早期"(换句话说:在PyDev环境中)出现这些错误,请将其更改为US-ASCII.另请参阅此解决方法的原始博客文章.
kir*_*ril 13
关于python2(仅限python2),前一些答案依赖于使用以下hack:
import sys
reload(sys) # Reload is a hack
sys.setdefaultencoding('UTF8')
Run Code Online (Sandbox Code Playgroud)
在我的情况下,它带来了副作用:我正在使用ipython笔记本,一旦我运行代码,'print'功能就不再起作用了.我想它会有解决方案,但我认为使用黑客攻击不应该是正确的选择.
在尝试了很多选项之后,那个适合我的选项就是使用相同的代码sitecustomize.py,而那段代码就是这样的.在评估该模块后,将从sys中删除setdefaultencoding函数.
所以解决方案是附加文件/usr/lib/python2.7/sitecustomize.py代码:
import sys
sys.setdefaultencoding('UTF8')
Run Code Online (Sandbox Code Playgroud)
当我使用virtualenvwrapper时,我编辑的文件是~/.virtualenvs/venv-name/lib/python2.7/sitecustomize.py.
当我使用python notebooks和conda时,它就是 ~/anaconda2/lib/python2.7/sitecustomize.py
关于它的博客文章很有见地.
请参阅https://anonbadger.wordpress.com/2015/06/16/why-sys-setdefaultencoding-will-break-code/.
我在下面解释它的内容.
在python 2中,对于字符串的编码没有强类型,你可以对不同编码的字符串执行操作,并且成功.例如,以下将返回True.
u'Toshio' == 'Toshio'
Run Code Online (Sandbox Code Playgroud)
这将适用于编码的每个(正常的,无前缀的)字符串,sys.getdefaultencoding()默认为ascii但不是其他字符串.
默认编码意味着在系统范围内更改site.py,但不在其他地方更改.在用户模块中设置它的hacks(也在这里展示)只是:hacks,而不是解决方案.
Python 3确实将系统编码更改为默认为utf-8(当LC_CTYPE具有unicode感知时),但是基本问题是通过在与unicode字符串一起使用时显式编码"字节"字符串的要求来解决的.
第一:reload(sys)仅根据输出终端流的需要设置一些随机默认编码是不好的做法。reload经常根据环境更改 sys 中已到位的内容 - 例如 sys.stdin/stdout 流、sys.excepthook 等。
print我所知道的解决unicode 字符串和超越 ascii编码问题的最佳解决方案str是:处理 sys.stdout (类似文件的对象),它是有能力并且可以选择性地容忍以下需求:
当sys.stdout.encoding出于None某种原因,或不存在,或错误地为假或“小于”标准输出终端或流的实际能力时,则尝试提供正确的.encoding属性。最后通过替换sys.stdout & sys.stderr为类似文件的翻译对象。
当终端/流仍然无法对所有出现的 unicode 字符进行编码时,并且当您不想中断时print因此而破坏 \ 时,您可以在翻译类文件对象中引入编码与替换行为。
这里有一个例子:
\n\n#!/usr/bin/env python\n# encoding: utf-8\nimport sys\n\nclass SmartStdout:\n def __init__(self, encoding=None, org_stdout=None):\n if org_stdout is None:\n org_stdout = getattr(sys.stdout, \'org_stdout\', sys.stdout)\n self.org_stdout = org_stdout\n self.encoding = encoding or \\\n getattr(org_stdout, \'encoding\', None) or \'utf-8\'\n def write(self, s):\n self.org_stdout.write(s.encode(self.encoding, \'backslashreplace\'))\n def __getattr__(self, name):\n return getattr(self.org_stdout, name)\n\nif __name__ == \'__main__\':\n if sys.stdout.isatty():\n sys.stdout = sys.stderr = SmartStdout()\n\n us = u\'aou\xc3\xa4\xc3\xb6\xc3\xbc\xd1\x84\xc5\xbc\xc3\x9f\xc2\xb2\'\n print us\n sys.stdout.flush()\nRun Code Online (Sandbox Code Playgroud)\n\n我认为更改全局默认编码(仅更改为 UTF-8)的唯一充分理由是考虑到应用程序源代码决策 - 而不是因为 I/O 流编码问题:为了在不强制的情况下将超出 ascii 的字符串文字写入代码始终使用u\'string\'unicode 转义样式。通过处理始终使用 ascii 或 UTF-8 纯字符串文字的 Python 2 或 Python 2 + 3 源代码基础,可以相当一致地完成此操作(尽管anonbadger的文章是这么说的) - 只要这些字符串可能会经历静默 unicode 转换并在模块之间移动或可能转到标准输出。为此,更喜欢“# encoding: utf-8 ”或 ascii(无声明)。更改或删除仍然以非常愚蠢的方式致命地依赖于 chr #127 之外的 ascii 默认编码错误的库(这在今天很少见)。
除了SmartStdout上述方案之外,还可以在应用程序启动时(和/或通过 sitecustomize.py)执行此操作 - 不使用reload(sys):
...\ndef set_defaultencoding_globally(encoding=\'utf-8\'):\n assert sys.getdefaultencoding() in (\'ascii\', \'mbcs\', encoding)\n import imp\n _sys_org = imp.load_dynamic(\'_sys_org\', \'sys\')\n _sys_org.setdefaultencoding(encoding)\n\nif __name__ == \'__main__\':\n sys.stdout = sys.stderr = SmartStdout()\n set_defaultencoding_globally(\'utf-8\') \n s = \'aou\xc3\xa4\xc3\xb6\xc3\xbc\xd1\x84\xc5\xbc\xc3\x9f\xc2\xb2\'\n print s\nRun Code Online (Sandbox Code Playgroud)\n\n这样,字符串文字和大多数操作(字符迭代除外)就可以舒适地工作,而无需考虑 unicode 转换,就好像只有 Python3 一样。\n文件 I/O 当然总是需要特别注意编码 - 就像 Python3 中一样。
\n\n注意:普通字符串会从 utf-8 隐式转换为 unicodeSmartStdout注意:在转换为输出流编码之前,
这是我用来生成与python2和python3兼容并始终生成utf8输出的代码的方法。我在别处找到了这个答案,但我不记得出处了。
这种方法的工作原理是替换sys.stdout一些不太像文件的东西(但仍然只使用标准库中的东西)。这很可能会导致您的底层库出现问题,但在您可以很好地控制如何通过框架使用 sys.stdout 的简单情况下,这可能是一种合理的方法。
sys.stdout = io.open(sys.stdout.fileno(), 'w', encoding='utf8')
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
264847 次 |
| 最近记录: |