【发布时间】:2015-11-24 14:53:03
【问题描述】:
TL;DR:我可以让 Python 3 使用除 unicode 之外的任何东西作为所有东西的默认编码吗?
我有一些用 Python 3 编写的脚本。在我自己的文件上运行时,它们运行良好,因为这些文件以 utf-8 编码并且通常只使用与 ASCII 兼容的子集。
现在我尝试在几十年前的源文件上使用相同的脚本,我得到了左右的 unicode 异常。完全有可能,这些文件是由编辑器在一年中使用不同的编码进行编辑的,因此每个文件的编码可能不同,甚至定义不明确。
如果我在 Python 2 中编写脚本,假定采用固定宽度编码,那么一切都会正常工作。无论如何,使用非 ascii 字符的部分仅在 cmets 中。
在 Python3 中,当编码未知且可能定义不明确时,干净的解决方案是仅对字节数组数据进行操作,但缺少 .format 函数以及需要在任何地方区分字节和 str 文字都是句法噩梦,而且太耗时,无法在我的脚本中修复,不值得。
是否可以将 sys.stdin、sys.stderr 和所有文件 opened 的假定默认编码更改为固定宽度编码?这样做可以让我的脚本以“字节输入,字节输出”的方式工作,这真的更适合我对 shell 脚本的使用(并且最终会更稳定)。
理想情况下,解决方案应该基于每个脚本并允许忽略环境变量。
基于https://stackoverflow.com/a/12823030/2075630,我能想到的最好的是
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="latin-1")
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding="latin-1")
sys.stdin = io.TextIOWrapper(sys.stdin.buffer, encoding="latin-1")
# To avoid changing individual `open` calls:
open_ = open
def open(*a,**b):
b["encoding"] = "latin-1"
return open_(*a,**b)
但这会导致 STDOUT 和 STDERR 流被大量缓冲,这对于 shell 脚本来说是不可取的。
【问题讨论】:
-
为什么你认为这会导致大量缓冲?您没有添加任何缓冲,而是删除了文本 I/O 包装器,将其替换为另一个包装器。这不会改变缓冲行为。
-
所以我会想到。但在添加行之前,脚本会在运行时产生输出。添加行后,输出将在处理完成后全部输出。显然,新的 TextIOWrapper 增加了缓冲。
-
TextIOWrapper()的唯一缓冲选项是line_buffering参数。将其设置为True以在写入换行符时向底层缓冲区发送隐式flush()。 -
谢谢,该参数部分解决了这个问题(因为不仅
"\n"而且"\r"似乎会导致刷新,这是某些状态消息所必需的)。您可以将该更改转换为我可以接受的答案(通过此更改,它可以满足我的要求)。 -
您始终可以在
print()语句中添加flush=True参数。
标签: python python-3.x encoding