众所周知,encode()
有一个用于编解码器错误处理的error
参数,例如:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# "发" and "财" are not available in 'big5' encoding
text = "发财了".encode('big5', errors='replace')
但是,errors
没有print()
个参数,如果我们只是写:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
print("发财了")
如果在带有big5编码的命令提示符下运行,则会引发UnicodeEncodeError
异常(例如,在繁体中文版Windows中)。
有没有办法让print()
行为像encode()
,它接受更多处理程序,例如replace
,backslashreplace
或xmlcharrefreplace
,以便字符串可以安全打印而不会引发异常吗?
答案 0 :(得分:2)
这是我目前的解决方案:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
def safeprint(*args, errors='backslashreplace', **kargs):
"""
Print safely and skips error decode.
Acts like print() with an additional "errors" argument to determine the
error handler for codec errors and accepts non-str-or-None types for the
"sep" and "end" arguments.
"""
e = (kargs['file'] if 'file' in kargs else sys.stdout).encoding
args = [str(x) for x in args]
sep = str(kargs['sep']) if 'sep' in kargs and kargs['sep'] is not None else " "
end = str(kargs['end']) if 'end' in kargs and kargs['end'] is not None else "\n"
text = sep.join(args) + end
kargs['sep'] = ""
kargs['end'] = ""
print(text.encode(e, errors).decode(e, errors), **kargs)
if __name__ == "__main__":
safeprint("Hello World!", "你好世界!", "ハローワールド", "हैलो वर्ल्ड")
safeprint("Hello World!", "你好世界!", "ハローワールド", "हैलो वर्ल्ड", errors="ignore")
safeprint("Hello World!", "你好世界!", "ハローワールド", "हैलो वर्ल्ड", errors="replace")
safeprint("Hello World!", "你好世界!", "ハローワールド", "हैलो वर्ल्ड", errors="backslashreplace")
safeprint("Hello World!", "你好世界!", "ハローワールド", "हैलो वर्ल्ड", errors="xmlcharrefreplace")
safeprint("Hello World!", "你好世界!", "ハローワールド", "हैलो वर्ल्ड", sep=None, end=str)
safeprint("Hello World!", "你好世界!", "ハローワールド", "हैलो वर्ल्ड", sep=" -发- ", end=" -财- \n")
with open("safeprint_big5.log", "w", encoding="big5") as f:
safeprint("Hello World!", "你好世界!", "ハローワールド", "हैलो वर्ल्ड", file=f)
with open("safeprint_gbk.log", "w", encoding="gbk") as f:
safeprint("Hello World!", "你好世界!", "ハローワールド", "हैलो वर्ल्ड", file=f)
with open("safeprint_utf8.log", "w", encoding="utf-8") as f:
safeprint("Hello World!", "你好世界!", "ハローワールド", "हैलो वर्ल्ड", file=f)
这种方法使自定义函数safeprint()
与原生print()
一样具有以下差异:
还有一个errors
参数来确定如何处理编解码器错误(backslashreplace
为默认值)。
sep
和end
参数接受str或None以外的类型。
safeprint()
检查本地print()
应该写入的输出文件的编码,然后对所有文本参数进行编码,因此所有可打印的字符都按原样打印,并打印所有不可打印的字符如转型。
尽管之前对所有正在打印的文本进行编码和解码似乎效率低下,但原生encode()
和decode()
基于C并且运行速度非常快。在测试中,我在utf8控制台中打印一些带有utf8兼容纯文本的文章5000次,原生print()
需要0:00:02.366799
,safeprint()
需要0:00:02.915871
。它证明了性能下降几乎可以忽略不计。
上述脚本可以保存为模块脚本,比如safeprint.py
。其他脚本可以使用from safeprint import safeprint
并使用safeprint()
,甚至可以使用from safeprint import safeprint as print
覆盖原生print()
,以便print()
可以像safeprint()
一样工作确实。
答案 1 :(得分:0)
使用try .. except block包装你的print函数,并捕获UnicodeEncodeError异常:
try:
print("发财了")
except UnicodeEncodeError:
handle_encode_error()
您可以决定如何在异常块中转换字符串。