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

jhiyze9q  于 2023-11-20  发布在  Python
关注(0)|答案(1)|浏览(167)

如何在Windows上将\n打印到stdout?这段代码在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#")

字符串

amrnrhlw

amrnrhlw1#

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

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

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

背景

Python 3的io模块旨在提供跨平台和跨实现(CPython,PyPy,IronPython,Jython)所有文件类对象的抽象基类RawIOBaseBufferedIOBase,和TextIOBase。它在_pyio模块中包含一个参考纯Python实现。原始io.FileIO实现的共同点是底层POSIX系统调用,如readwrite,这消除了CRT stdio不一致的问题。在Windows上,POSIX层只是CRT的低I/O层,但至少限于单一平台的怪癖。
Windows的一个怪癖是在POSIX I/O层中有非标准的文本和二进制模式。Python通过始终使用二进制模式并在stdio文件描述符上调用setmode来解决这个问题。
Python可以通过实现RawIOBaseWinFileIO注册子类来避免使用Windows CRT进行I/O。在issue 12939中有一个建议的补丁。另一个例子是win_unicode_console模块,它实现了WindowsConsoleRawReaderWindowsConsoleRawWriter类。
1.这给那些嵌入Python并希望stdio使用默认文本模式的程序带来了问题。例如,在二进制模式下打印宽字符串不再像在ANSI文本模式下那样转换为char,而且它肯定不会像在UTF-16文本模式下那样使用WriteConsoleW打印。例如:

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

相关问题