【发布时间】:2021-09-23 20:48:51
【问题描述】:
TL;DR
尝试将字符串写入文件时发生以下错误:
代码
logfile.write(cli_args.last_name)
输出
UnicodeEncodeError: 'ascii' codec can't encode characters in position 8-9: ordinal not in range(128)
但这有效:
代码
print(cli_args.last_name)
输出
佩雷斯
为什么?
完整上下文
我编写了一个脚本,它从 Linux CLI 接收数据,对其进行处理,最后使用提供的数据创建 Zendesk 票证。它是一种 CLI API,因为在我的脚本之前有一个更大的系统,它有一个带有表单的 Web 界面,用户可以在其中填写字段的值,然后替换为 CLI 脚本。例如:
myscript.py --first_name '_first_name_' --last_name '_last_name_'
直到昨天更新网络时,该脚本都可以正常运行。我认为他们更改了与字符集或编码相关的内容。
我通过打开一个文件并编写一些信息性消息来使用 F 字符串进行一些简单的日志记录,以防万一发生任何故障,因此我可以回去检查它发生的位置。此外,使用 argparse 模块读取 CLI 属性。示例:
logfile.write(f"\tChecking for opened tickets for user '{cli_args.first_name} {cli_args.last_name}'\n")
网站更新后,我收到如下错误:
UnicodeEncodeError: 'ascii' 编解码器无法在位置编码字符 8-9:序数不在范围内(128)
做一些故障排除我发现这是因为一些用户输入带有重音符号的名称,例如Carlos Pérez。
我需要脚本再次运行并为这样的输入做好准备,所以我通过检查 Web 控制台输入表单中的 HTTP 标头来寻找答案,发现它使用了Content-Type: text/html; charset=UTF-8;我的第一次尝试是将 CLI 参数中传递的 str 编码到 utf-8 并使用相同的编解码器再次解码,但没有成功。
第二次尝试时,我检查了 Python 文档 str.encode() 和 bytes.decode()。所以我尝试了这个:
logfile.write(
"\tChecking for opened tickets for user "
f"'{cli_args.first_name.encode(encoding='utf-8', errors='ignore').decode('utf-8')} "
f"{cli_args.last_name.encode(encoding='utf-8', errors='ignore').decode('utf-8')}'"
)
它起作用了,但删除了带有重音符号的字母,所以Carlos Pérez 变成了Carlos Prez,在这种情况下这对我没有用,我需要完整的输入。
作为一个绝望的举动,我尝试打印我试图写入日志文件的相同 F 字符串,令我惊讶的是它起作用了。它在没有任何编码/解码过程的情况下打印到控制台Carlos Pérez。
打印是如何工作的?为什么尝试写入文件不起作用?但最重要的是如何写入与打印格式相同的文件?
编辑 1 @MarkTolonen
尝试了以下方法:
logfile = open("/usr/share/pandora_server/util/plugin/plugin_mcm/sandbox/755bug.txt", mode="a", encoding="utf8")
logfile.write(cli_args.body)
logfile.close()
输出:
Traceback(最近一次调用最后一次): 文件“/usr/share/pandora_server/util/plugin/plugin_mcm/sandbox/ticket_query_app.py”,第 414 行,在 主要的() 文件“/usr/share/pandora_server/util/plugin/plugin_mcm/sandbox/ticket_query_app.py”,第 81 行,在 main logfile.write(cli_args.body) UnicodeEncodeError: 'utf-8' codec can't encode characters in position 8-9: surrogates not allowed
编辑 2
我设法得到了导致问题的文本:
if __name__ == "__main__":
string = (
"Buenos d\udcc3\udcadas,\r\n\r\n"
"Mediante monitoreo autom\udcc3\udca1tico se ha detectado un evento fuera de lo normal:\r\n\r\n"
"Descripci\udcc3\udcb3n del evento: _snmp_f13_\r\n"
"Causas sugeridas del evento: _snmp_f14_\r\n"
"Posible afectaci\udcc3\udcb3n del evento: _snmp_f15_\r\n"
"Validaciones de bajo impacto: _snmp_f16_\r\n"
"Fecha y hora del evento: 2021-07-14 17:47:51\r\n\r\n"
"Saludos."
)
# Output: Text with the unicodes translated
print(string)
# Output: "UnicodeEncodeError: 'utf-8' codec can't encode characters in position 8-9: surrogates not allowed"
with open(file="test.log", mode="w", encoding="utf8") as logfile:
logfile.write(string)
【问题讨论】:
-
你是如何创建
logfile的? -
这是在 Windows 还是 Linux 上运行?您可以指定文件在打开时应为 UTF-8。你可以说
print("string string string", file=logfile)而不是写。 -
使用上述信息编辑您的问题。打开文件时使用
encoding='utf8'选项支持所有Unicode字符。 -
以防万一,@MarkTolonen 有正确的答案。只需在打开文件时将文件声明为 UTF-8。问题解决了。 Linux 上的 stdin/stdout 就是这样打开的。
标签: python python-3.x string file write