使用 Python 3 将 LF 打印到 Windows 标准输出 [英] Print LF with Python 3 to Windows stdout

查看:45
本文介绍了使用 Python 3 将 LF 打印到 Windows 标准输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

How to get \n printed to stdout on Windows? This code works in Python 2, but not with 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 实现来进行换行转换.您可以手动调用 sys.stdout.buffer.write 来使用二进制模式 BufferedWriterprint代码>.如果您需要使用 print,那么您将需要一个不使用通用换行符的新文本 I/O 包装器.例如:

Python 3 already configures standard I/O in binary mode, but it has its own I/O implementation that does newline translation. Instead of using print, which requires a text-mode file, you could manually call sys.stdout.buffer.write to use the binary-mode BufferedWriter. If you need to use print, then you'll need a new text I/O wrapper that doesn't use universal newlines. For example:

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__.

Since closefd is false, closing this file won't close the original sys.stdout file descriptor. You can use this file explicitly via print("#\n#", file=stdout), or replace sys.stdout = stdout. The original is available as sys.__stdout__.

背景

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

Python 3's io module was designed to provide a cross-platform and cross-implementation (CPython, PyPy, IronPython, Jython) specification for all filelike objects in terms of the abstract base classes RawIOBase, BufferedIOBase, and TextIOBase. It includes a reference pure Python implementation in the _pyio module. The common denominator for the raw io.FileIO implementation is the set of low-level POSIX system calls such as read and write, which eliminates the problem of CRT stdio inconsistencies. On Windows, the POSIX layer is just the low I/O layer of the CRT, but at least that's limited to the quirks of a single platform.

Windows 的一个怪癖是在其 POSIX I/O 层具有非标准文本和二进制模式.Python 通过始终使用二进制模式并在 stdio 文件描述符 1 上调用 setmode 来解决此问题.

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 可以通过实现 RawIOBaseWinFileIO 注册子类来避免使用 Windows CRT 进行 I/O.在 issue 12939 中有一个建议的补丁.另一个例子是 win_unicode_console 模块,它实现了 WindowsConsoleRawReaderWindowsConsoleRawWriter 类.

Python can avoid using the Windows CRT for I/O by implementing a WinFileIO registered subclass of RawIOBase. There's a proposed patch for this in issue 12939. Another example is the win_unicode_console module, which implements WindowsConsoleRawReader and WindowsConsoleRawWriter classes.

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

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

这篇关于使用 Python 3 将 LF 打印到 Windows 标准输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆