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

ana*_*nik 6 windows stdout python-3.x

如何\n在Windows上打印到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#")
Run Code Online (Sandbox Code Playgroud)

Ery*_*Sun 6

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)
Run Code Online (Sandbox Code Playgroud)

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

背景

Python 3中的io模块的目的是提供一种跨平台和跨实现(CPython的,PyPy,IronPython的,Jython的)规范的所有类文件中的对象抽象基类的术语RawIOBase,BufferedIOBaseTextIOBase.它包含_pyio模块中的参考纯Python实现.原始io.FileIO实现的共同点是一组低级POSIX系统调用,例如readwrite,它消除了CRT stdio不一致的问题.在Windows上,POSIX层只是CRT的低I/O层,但至少仅限于单个平台的怪癖.

其中一个Windows怪癖是在其POSIX I/O层中使用非标准文本和二进制模式.Python总是使用二进制模式并调用setmodestdio文件描述符1来解决这个问题.

Python可以通过实现避免使用Windows CRT的I/O WinFileIO注册的子类RawIOBase.问题12939中有一个提议的补丁.另一个例子是win_unicode_console模块,它实现了类WindowsConsoleRawReaderWindowsConsoleRawWriter类.


这给嵌入Python的程序带来了问题,并期望stdio使用默认的文本模式.例如,在二进制模式下,打印宽字符字符串不再char像在ANSI文本模式中那样进行转换,并且它肯定不会WriteConsoleW像在UTF-16文本模式中那样使用打印.例如:

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
Run Code Online (Sandbox Code Playgroud)

  • 换行符的自动转换可能很难追踪。当在 atom 的 [process-palletette](https://atom.io/packages/process-palette)(https://atom.io/packages/process-palette) 中查看输出时,我的 `print` 似乎将换行符加倍时,我确切地知道发生了什么,但我没有知道*如何*禁用通用换行符转换——当然,我直接调用`sys.stdout.write()`的尝试也失败了——离问题更近了一步,但仍然是错误的。您重新定义 `sys.stdout` 的代码运行良好,谢谢。 (2认同)