Aumentar el tamaño del búfer de salida estándar de Python

Nov 26 2020

¿Hay alguna manera de aumentar el stdouttamaño del búfer de 8182 en Python o de retrasar el vaciado hasta que realmente llame flush?

Cosas que he probado que no funcionan:

  • Puedo solucionar este problema en Windows porque puedo acceder al búfer directamente (por ejemplo, vea mi respuesta a esta publicación ). Pero esto no funciona para Unix.
  • Puedo aumentar el tamaño del búfer para un archivo pasándolo bufferal constructor, sin embargo, stdoutya está construido.
  • ¡Desactivar el almacenamiento en búfer ( python -u) obviamente empeora las cosas!
  • El uso de un búfer temporal encuentra los mismos problemas: stdoutse vacía después de que cada 8192o byte se copia del búfer temporal.

Justificación: el objetivo aquí es reducir el parpadeo de la consola. El almacenamiento en búfer de todo, según esta pregunta , funciona, por ejemplo, cuando lo intento en C o usando la API de Windows en Python, pero el límite de 8182 en Python parece estar causando problemas que no puedo solucionar en Unix.

Respuestas

1 blhsing Nov 27 2020 at 05:29

Puede envolver el flujo de salida estándar sin procesar, disponible como sys.stdout.buffer, con un tamaño de búfer más grande con io.BufferedWriter, y luego envolver el flujo binario almacenado en búfer resultante como un flujo de texto almacenado en búfer con io.TextIOWrapper:

import io
import sys

sys.stdout = io.TextIOWrapper(io.BufferedWriter(sys.stdout.buffer, new_size))

A continuación, se muestra una demostración del efecto de aumentar el tamaño del búfer de la salida estándar a 100000 para que no elimine las dos salidas de impresión de 10000 caracteres hasta que se llame a una descarga manual:

import io
import sys
import time

print('Original buffer size:', io.DEFAULT_BUFFER_SIZE)
for large_buffer in False, True:
    if large_buffer:
        print('Increasing buffer size...')
        sys.stdout = io.TextIOWrapper(io.BufferedWriter(sys.stdout.buffer, 100000))
    for i in range(2):
        time.sleep(2)
        print(str(i * 2) * 10000)
        time.sleep(2)
        print(str(i * 2 + 1) *10000)
        print(f'Flush #{i + 1}')
        sys.stdout.flush()

Manifestación: https://repl.it/@blhsing/UnkemptGullibleDecompiler

1 cz Nov 27 2020 at 16:39

Encontré la respuesta, en realidad muy simple:

my_stdout = open( 1, "w", buffering = 100000 )
  • 1es el filenopara stdout.
  • sys.stdout = my_stdoutse puede utilizar para realizar el cambio en el printdestino predeterminado .
  • Solo lo he probado en Unix.