Печать LF с Python 3 на стандартный вывод Windows

Как получить \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#")

1 ответ

Решение

Python 3 уже настраивает стандартный ввод / вывод в двоичном режиме, но у него есть собственная реализация ввода / вывода, которая выполняет перевод новой строки. Вместо того, чтобы использовать print, который требует файл в текстовом режиме, вы можете вызвать вручную sys.stdout.buffer.write использовать бинарный режим BufferedWriter, Если вам нужно использовать print тогда вам понадобится новая оболочка ввода / вывода текста, которая не использует универсальные переводы строк. Например:

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) для всех файловоподобных объектов в терминах абстрактных базовых классов. RawIOBase, BufferedIOBase, а также TextIOBase, Он включает эталонную чистую реализацию Python в _pyio модуль. Общий знаменатель для сырья io.FileIO реализация представляет собой набор системных вызовов низкого уровня POSIX, таких как read а также write, что устраняет проблему несоответствий CRT stdio. В Windows уровень POSIX - это просто низкий уровень ввода-вывода CRT, но по крайней мере он ограничен особенностями одной платформы.

Одна из особенностей Windows - наличие нестандартного текстового и двоичного режимов в слое ввода / вывода POSIX. Python решает эту проблему, всегда используя двоичный режим и вызывая setmode в файловых дескрипторах stdio 1.

Python может избежать использования Windows CRT для ввода / вывода, реализовав WinFileIO зарегистрированный подкласс RawIOBase, Предлагается патч для этого в выпуске 12939. Другим примером является модуль win_unicode_console, который реализует WindowsConsoleRawReader а также WindowsConsoleRawWriter классы.


1. Это вызвало проблемы для программ, которые встраивают 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

Другие вопросы по тегам