使用 Python 3 将 LF 打印到 Windows 标准输出

2023-12-24

如何获得\n在 Windows 上打印到标准输出?此代码适用于 Python 2,但不适用于 Python 3:

# set sys.stdout to binary mode on Windows
import sys, os, msvcrt
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)

# the length of testfile created with
#     python test_py3k_lf_print.py > testfile
# below should be exactly 4 symbols (23 0A 23 0A)
print("#\n#")

Python 3 已经在二进制模式下配置了标准 I/O,但它有自己的 I/O 实现来进行换行转换。而不是使用print,这需要一个文本模式文件,你可以手动调用sys.stdout.buffer.write使用二进制模式BufferedWriter。如果您需要使用print,那么您将需要一个不使用通用换行符的新文本 I/O 包装器。例如:

stdout = open(sys.__stdout__.fileno(), 
              mode=sys.__stdout__.mode, 
              buffering=1, 
              encoding=sys.__stdout__.encoding, 
              errors=sys.__stdout__.errors, 
              newline='\n', 
              closefd=False)

Since closefd为 false,关闭此文件不会关闭原始文件sys.stdout文件描述符。您可以通过显式使用此文件print("#\n#", file=stdout),或替换sys.stdout = stdout。原件可作为sys.__stdout__.

背景

Python 3 的io模块旨在根据抽象基类为所有类文件对象提供跨平台和跨实现(CPython、PyPy、IronPython、Jython)规范RawIOBase, BufferedIOBase, and TextIOBase。它包括一个参考纯Python实现_pyio模块。原始数据的共同点io.FileIO实现是一组低级 POSIX 系统调用,例如read and write,这就消除了CRT stdio不一致的问题。在 Windows 上,POSIX 层只是 CRT 的低 I/O 层,但至少这仅限于单个平台的怪癖。

One of the Windows quirks is having non-standard text and binary modes in its POSIX I/O layer. Python addresses this by always using binary mode and calling setmode on the stdio file descriptors 1.

Python 可以通过实现一个方法来避免使用 Windows CRT 进行 I/OWinFileIO的注册子类RawIOBase。有一个针对此问题的建议补丁问题 12939 http://bugs.python.org/issue12939。另一个例子是win_unicode_console https://github.com/Drekin/win-unicode-console模块,它实现WindowsConsoleRawReader and WindowsConsoleRawWriter类。


1. This has caused problems for programs that embed Python and expect stdio to use the default text mode. For example, in binary mode printing wide-character strings no longer casts to char as it does in ANSI text mode, and it certainly doesn't print using WriteConsoleW as it would in UTF-16 text mode. For example:

Python 2.7.10 (default, May 23 2015, 09:44:00) 
[MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys, os, msvcrt, ctypes 
>>> ctypes.cdll.msvcr90.wprintf(b'w\x00i\x00d\x00e\x00\n\x00') 
wide
5
>>> msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) 
16384
>>> ctypes.cdll.msvcr90.wprintf(b'w\x00i\x00d\x00e\x00\n\x00')
w i d e
 5
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Python 3 将 LF 打印到 Windows 标准输出 的相关文章

随机推荐