Aumentar o tamanho do buffer padrão do Python

Nov 26 2020

Existe uma maneira de aumentar o stdouttamanho do buffer de 8182 em Python ou atrasar a liberação até que eu realmente chame flush?

Coisas que tentei que não funcionam:

  • Eu posso contornar este problema no Windows porque posso acessar o buffer diretamente (por exemplo, veja minha resposta a esta postagem ). Mas isso não funciona para Unix.
  • Posso aumentar o tamanho do buffer de um arquivo passando bufferpara o construtor, mas stdoutjá está construído.
  • Desativar o buffer ( python -u) obviamente torna as coisas piores!
  • Usar um buffer temporário encontra os mesmos problemas - stdouté liberado após cada 8192º byte é copiado do buffer temporário.

Justificativa: O objetivo aqui é reduzir a oscilação do console. Armazenar tudo em buffer, de acordo com essa pergunta, de fato funciona, por exemplo quando tento em C ou usando a API do Windows em Python, mas o limite de 8182 em Python parece estar causando problemas que não consigo contornar no Unix.

Respostas

1 blhsing Nov 27 2020 at 05:29

Você pode agrupar o fluxo stdout bruto, disponível como sys.stdout.buffer, com um tamanho de buffer maior com io.BufferedWritere, em seguida, agrupar o fluxo binário em buffer resultante como um fluxo de texto em buffer com io.TextIOWrapper:

import io
import sys

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

Aqui está uma demonstração do efeito de aumentar o tamanho do buffer de stdout para 100.000, de modo que não libere as duas saídas de impressão de 10.000 caracteres até que uma descarga manual seja chamada:

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()

Demo: https://repl.it/@blhsing/UnkemptGullibleDecompiler

1 cz Nov 27 2020 at 16:39

Encontrei a resposta, na verdade muito simples:

my_stdout = open( 1, "w", buffering = 100000 )
  • 1é o filenopara stdout.
  • sys.stdout = my_stdoutpode ser usado para fazer a alteração no printdestino padrão .
  • Eu só testei isso no Unix.