Com que frequência o python é liberado para um arquivo?

228
  1. Com que frequência o Python libera um arquivo?
  2. Com que frequência o Python libera o stdout?

Não tenho certeza sobre (1).

Quanto ao (2), acredito que o Python libere stdout após cada nova linha. Mas, se você sobrecarregar o stdout para um arquivo, ele será liberado com tanta frequência?

Tim McJilton
fonte

Respostas:

332

Para operações de arquivo, o Python usa o buffer padrão do sistema operacional, a menos que você o configure de outra forma. Você pode especificar um tamanho de buffer, sem buffer ou com linha.

Por exemplo, a função aberta usa um argumento de tamanho do buffer.

http://docs.python.org/library/functions.html#open

"O argumento de buffer opcional especifica o tamanho do buffer desejado do arquivo:"

  • 0 significa sem buffer,
  • 1 significa linha em buffer,
  • qualquer outro valor positivo significa usar um buffer (aproximadamente) desse tamanho.
  • Um buffer negativo significa usar o padrão do sistema, que geralmente é buffer de linha para dispositivos tty e totalmente buffer para outros arquivos.
  • Se omitido, o padrão do sistema é usado.

código:

bufsize = 0
f = open('file.txt', 'w', buffering=bufsize)
Corey Goldberg
fonte
23
+1 para a parte "linha em buffer". Era exatamente o que eu estava procurando e funciona como um encanto.
reinício
2
Usando o Python 3.4.3 quando open('file.txt', 'w', 1)eu recebo o buffer de linha adequado. Mas se eu fizer algo maior (eu queria open('file.txt', 'w', 512)), ele armazena em buffer o io.DEFAULT_BUFFER_SIZE8192. Isso é um bug do Python, do Linux ou do ID10t?
Bruno Bronosky
É possível alterar o buffer para os fluxos já abertos ? Digamos, quero stdoutreceber um buffer de linha, independentemente de ser um console ou redirecionado para um arquivo?
23618 Mikhail T.
1
@CharlieParker quando você chama write()um identificador de arquivo, a saída é armazenada em buffer na memória e acumulada até que o buffer esteja cheio ... quando o buffer é "liberado" (o conteúdo é gravado do buffer no arquivo). Você pode liberar explicitamente o buffer chamando o flush()método em um identificador de arquivo.
Corey Goldberg
3
Observe que o buffer sem buffer (0) está disponível apenas no modo binário e a linha com buffer (1) está disponível apenas no modo texto.
ZaydH
172

Você também pode forçar a liberação do buffer para um arquivo programaticamente com o flush()método

with open('out.log', 'w+') as f:
    f.write('output is ')
    # some work
    s = 'OK.'
    f.write(s)
    f.write('\n')
    f.flush()
    # some other work
    f.write('done\n')
    f.flush()

Eu achei isso útil ao seguir um arquivo de saída com tail -f.

Kortina
fonte
54
Da documentação:Note: flush() does not necessarily write the file’s data to disk. Use flush() followed by os.fsync() to ensure this behavior.
bobismijnnaam
1
@bobismijnnaam link da próxima vez para esses documentos. A única referência que posso encontrar é de github.com/jprzywoski/python-reference/blob/master/source/docs/… e não sei quem é.
de Bruno Bronosky
5
@Bruno Bronosky Bom argumento. Docs: Note: flush() does not necessarily write the file’s data to disk. Use flush() followed by os.fsync() to ensure this behavior.
bobismijnnaam
O que estou confuso é o que o termo flushingsignifica. Por que precisamos disso? Para que serve? por que eu deveria me importar com isso?
Charlie Parker
@CharlieParker quando você escreve, grava em uma cópia (parte) do arquivo na RAM, que pode não ser salva no disco por um tempo. Melhora o desempenho, mas pode significar perda de dados se essa cópia nunca for gravada (disco removido, falha do SO, etc.). flush () diz ao Python para gravar imediatamente esse buffer no disco. (Então, os.fsync () diz ao sistema operacional para fazê-lo. Existem muitas camadas de buffers ...)
Rena
13

Não sei se isso também se aplica ao python, mas acho que depende do sistema operacional que você está executando.

No Linux, por exemplo, a saída para o terminal libera o buffer em uma nova linha, enquanto que para a saída para arquivos, ele libera apenas quando o buffer está cheio (por padrão). Isso ocorre porque é mais eficiente liberar o buffer menos vezes e é menos provável que o usuário note se a saída não for liberada em uma nova linha de um arquivo.

Você pode liberar automaticamente a saída, se é isso que você precisa.

EDIT: Eu acho que você iria liberar automaticamente em python desta maneira (com base aqui )

#0 means there is no buffer, so all output
#will be auto-flushed
fsock = open('out.log', 'w', 0)
sys.stdout = fsock
#do whatever
fsock.close()
KLee1
fonte
12

Você também pode verificar o tamanho do buffer padrão chamando o atributo DEFAULT_BUFFER_SIZE somente leitura do módulo io.

import io
print (io.DEFAULT_BUFFER_SIZE)
N Randhawa
fonte
1
Obrigado! É bom saber que o python define como o sistema operacional define ... mas isso ajuda a descobrir o que o sistema operacional pré-define.
Cometsong
2

Aqui está outra abordagem, até o OP para escolher qual ele prefere.

Ao incluir o código abaixo no __init__arquivo .py antes de qualquer outro código, as mensagens impressas printe os erros não serão mais registrados no Log.txt do Ableton, mas para separar os arquivos no seu disco:

import sys

path = "/Users/#username#"

errorLog = open(path + "/stderr.txt", "w", 1)
errorLog.write("---Starting Error Log---\n")
sys.stderr = errorLog
stdoutLog = open(path + "/stdout.txt", "w", 1)
stdoutLog.write("---Starting Standard Out Log---\n")
sys.stdout = stdoutLog

(para Mac, mude #username#para o nome da sua pasta de usuário. No Windows, o caminho para a pasta do usuário terá um formato diferente)

Quando você abre os arquivos em um editor de texto que atualiza seu conteúdo quando o arquivo no disco é alterado (exemplo: Mac: o TextEdit não faz, mas o TextWrangler), você verá os logs sendo atualizados em tempo real.

Créditos: esse código foi copiado principalmente dos scripts da superfície de controle do liveAPI por Nathan Ramella

Mattijs
fonte