Aumenta la dimensione del buffer stdout di Python

Nov 26 2020

C'è un modo per aumentare la stdoutdimensione del buffer da 8182 in Python o per ritardare il lavaggio fino a quando non chiamo effettivamente flush?

Cose che ho provato che non funzionano:

  • Posso aggirare questo problema su Windows perché posso accedere direttamente al buffer (ad esempio, vedere la mia risposta a questo post ). Ma questo non funziona per Unix.
  • Posso aumentare la dimensione del buffer per un file passando bufferal costruttore, tuttavia stdoutè già costruito.
  • La disattivazione del buffering ( python -u) ovviamente peggiora le cose!
  • L'utilizzo di un buffer temporaneo incontra gli stessi problemi: stdoutviene scaricato dopo che ogni 8192 byte viene copiato dal buffer temporaneo.

Motivazione: l'obiettivo qui è ridurre lo sfarfallio della console. Il buffering di tutto, come da questa domanda funziona davvero, ad esempio quando provo in C o utilizzando l'API di Windows in Python, ma il limite di 8182 in Python sembra causare problemi che non riesco a aggirare su Unix.

Risposte

1 blhsing Nov 27 2020 at 05:29

Puoi racchiudere il flusso stdout grezzo, disponibile come sys.stdout.buffer, con una dimensione del buffer più grande con io.BufferedWriter, e quindi avvolgere il flusso binario bufferizzato risultante come flusso di testo bufferizzato con io.TextIOWrapper:

import io
import sys

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

Ecco una dimostrazione dell'effetto dell'aumento della dimensione del buffer di stdout a 100000 in modo che non scarichi i due output di stampa lunghi 10000 caratteri fino a quando non viene chiamato un flush manuale:

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

Trovato la risposta, in realtà molto semplice:

my_stdout = open( 1, "w", buffering = 100000 )
  • 1è il filenoper stdout.
  • sys.stdout = my_stdoutpuò essere utilizzato per apportare la modifica alla printdestinazione predefinita .
  • L'ho provato solo su Unix.