O que exatamente o file.flush () do Python está fazendo?


137

Encontrei isso na documentação do Python para objetos de arquivo :

flush () não grava necessariamente os dados do arquivo no disco. Use flush () seguido por os.fsync () para garantir esse comportamento.

Então, minha pergunta é: o que exatamente o Python está flushfazendo? Eu pensei que isso força a gravação de dados no disco, mas agora vejo que não. Por quê?

Respostas:


220

Normalmente, existem dois níveis de buffer envolvidos:

  1. Buffers internos
  2. Buffers do sistema operacional

Os buffers internos são buffers criados pelo tempo de execução / biblioteca / linguagem contra os quais você está programando e devem acelerar as coisas, evitando chamadas do sistema para cada gravação. Em vez disso, quando você grava em um objeto de arquivo, grava em seu buffer e sempre que o buffer é preenchido, os dados são gravados no arquivo real usando chamadas do sistema.

No entanto, devido aos buffers do sistema operacional, isso pode não significar que os dados sejam gravados no disco . Pode apenas significar que os dados são copiados dos buffers mantidos pelo seu tempo de execução nos buffers mantidos pelo sistema operacional.

Se você escrever algo e ele terminar no buffer (somente), e a energia for cortada em sua máquina, esses dados não estarão no disco quando a máquina for desligada.

Portanto, para ajudar você a ter os métodos flushe fsync, em seus respectivos objetos.

O primeiro flush,, simplesmente escreverá todos os dados que permanecem em um buffer de programa no arquivo real. Normalmente, isso significa que os dados serão copiados do buffer do programa para o buffer do sistema operacional.

Especificamente, o que isso significa é que, se outro processo tiver o mesmo arquivo aberto para leitura, ele poderá acessar os dados que você acabou de liberar para o arquivo. No entanto, isso não significa necessariamente que ele foi "permanentemente" armazenado no disco.

Para fazer isso, é necessário chamar o os.fsyncmétodo que garante que todos os buffers do sistema operacional sejam sincronizados com os dispositivos de armazenamento para os quais eles são, ou seja, esse método copiará os dados dos buffers do sistema operacional para o disco.

Normalmente, você não precisa se preocupar com nenhum dos métodos, mas se estiver em um cenário em que a paranóia sobre o que realmente acaba em disco é uma coisa boa, faça as duas chamadas conforme as instruções.


Adendo em 2018.

Observe que agora os discos com mecanismos de cache são muito mais comuns do que em 2013, então agora há ainda mais níveis de cache e buffers envolvidos. Eu assumir estes buffers serão tratadas pelas chamadas de sincronização / lave bem, mas eu realmente não sei.


10
Quando uso a with file('blah') as fd: #dostuffconstrução, sei que ela garante o fechamento do descritor de arquivo. Também libera ou sincroniza?
Marcin

3
@ Marcin: Ele libera, mas não sincroniza.
que você

8
fsyncé necessário para a atomicidade. você não pode esperar fechar um arquivo, reabri-lo e encontrar seu conteúdo sem um fsyncno meio. Geralmente funciona, mas não no linux com ext4 e opções de montagem padrão, por exemplo. Também fsyncnão é garantido que você realmente gire o ferro nos pratos, porque 1: fsync pode ser desativado (no modo laptop) e 2: o buffer interno do disco rígido pode não ser instruído a lavar.
precisa saber é o seguinte

1
existe alguma maneira de liberar o buffer de um sistema operacional para todos os arquivos, se o arquivo for gravado por outro processo?
Nacht

1
O fsync é relativamente caro. Em geral, você não está escrevendo um software de missão crítica que precisa de 100% de conformidade com ACID e durabilidade para acessar o disco, e se o fizer, provavelmente está dolorosamente ciente disso e deve estar ciente das etapas que você pode seguir para obter essas garantias. . A chamada de fsync aguardará o acesso do disco físico para gravar os dados no disco, enquanto a liberação e o fechamento aguardarão apenas que os dados sejam movidos para a memória cache. A diferença de velocidade é provavelmente de várias ordens de magnitude.
Lasse V. Karlsen

10

Porque o sistema operacional pode não fazer isso. A operação de liberação força os dados do arquivo para o cache de arquivos na RAM e, a partir daí, é tarefa do sistema operacional enviá-los para o disco.


6
Você está certo, mas actuallyé relativo aqui: se o dispositivo de destino tiver o cache de gravação ativado, os dados poderão não ter atingido os pratos / chips reais quando os.fsync()retornarem.
Frédéric Hamidi

7

Ele libera o buffer interno, o que supostamente faz com que o sistema operacional grave o buffer no arquivo. [1] O Python usa o buffer padrão do sistema operacional, a menos que você o configure de outra forma.

Mas, às vezes, o sistema operacional ainda escolhe não cooperar. Especialmente com coisas maravilhosas, como atrasos de gravação no Windows / NTFS. Basicamente, o buffer interno é liberado, mas o buffer do sistema operacional ainda o mantém. Então você precisa dizer ao sistema operacional para gravá-lo em disco os.fsync()nesses casos.

[1] http://docs.python.org/library/stdtypes.html


0

Basicamente, o flush () limpa seu buffer de RAM, seu poder real é que ele permite que você continue gravando posteriormente - mas não deve ser considerado o melhor / mais seguro recurso de gravação em arquivo. Está liberando sua RAM para mais dados, isso é tudo. Se você deseja garantir que os dados sejam gravados no arquivo com segurança, use close ().

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.