Se você ler um arquivo inteiro com, content = open('Path/to/file', 'r').read()
o identificador de arquivo fica aberto até o script sair? Existe um método mais conciso para ler um arquivo inteiro?
fonte
Se você ler um arquivo inteiro com, content = open('Path/to/file', 'r').read()
o identificador de arquivo fica aberto até o script sair? Existe um método mais conciso para ler um arquivo inteiro?
A resposta para essa pergunta depende um pouco da implementação específica do Python.
Para entender do que se trata, preste atenção especial ao file
objeto real . No seu código, esse objeto é mencionado apenas uma vez, em uma expressão, e fica inacessível imediatamente após o read()
retorno da chamada.
Isso significa que o objeto do arquivo é lixo. A única pergunta restante é "Quando o coletor de lixo coletará o objeto de arquivo?".
no CPython, que usa um contador de referência, esse tipo de lixo é percebido imediatamente e, portanto, será coletado imediatamente. Isso geralmente não é verdade para outras implementações python.
Uma solução melhor, para garantir que o arquivo esteja fechado, é este padrão:
with open('Path/to/file', 'r') as content_file:
content = content_file.read()
que sempre fechará o arquivo imediatamente após o término do bloco; mesmo se ocorrer uma exceção.
Edit: Para colocar um ponto mais fino nele:
Diferente de file.__exit__()
, que é "automaticamente" chamado em uma with
configuração de gerenciador de contexto, a única outra maneira que file.close()
é automaticamente chamada (ou seja, que não seja explicitamente chamada por si mesmo) é via file.__del__()
. Isso nos leva à questão de quando é __del__()
chamado?
Um programa gravado corretamente não pode assumir que os finalizadores serão executados a qualquer momento antes do encerramento do programa.
- https://devblogs.microsoft.com/oldnewthing/20100809-00/?p=13203
Em particular:
Os objetos nunca são explicitamente destruídos; no entanto, quando se tornam inacessíveis, podem ser coletados no lixo. É permitido que uma implementação adie a coleta de lixo ou a omita por completo - é uma questão de qualidade da implementação como a coleta de lixo é implementada, desde que nenhum objeto seja coletado que ainda esteja acessível.
[...]
Atualmente, o CPython usa um esquema de contagem de referência com detecção atrasada (opcional) de lixo vinculado ciclicamente, que coleta a maioria dos objetos assim que eles se tornam inacessíveis, mas não é garantido coletar lixo contendo referências circulares.
- https://docs.python.org/3.5/reference/datamodel.html#objects-values-and-types
(Ênfase minha)
mas, como sugere, outras implementações podem ter outro comportamento. Como exemplo, o PyPy possui 6 implementações diferentes de coleta de lixo !
__exit__()
nesses casos parece uma falha de design.try
/finally
complicado e a inutilidade altamente comum dos manipuladores de limpeza quewith
resolvem. A diferença entre "fechar explicitamente" e "gerenciar comwith
" é que o manipulador de saída é chamado mesmo se uma exceção for lançada. Você pode incluirclose()
umafinally
cláusula, mas isso não é muito diferente de usarwith
, um pouco mais confuso (3 linhas extras em vez de 1) e um pouco mais difícil de acertar.with foo() as f: [...]
é basicamente o mesmo quef = foo()
,f.__enter__()
[...] ef.__exit__()
com exceções manipuladas , de modo que__exit__
é sempre chamado. Portanto, o arquivo sempre é fechado.Você pode usar o pathlib .
Para Python 3.5 e superior:
Para versões mais antigas do Python, use pathlib2 :
Então:
Esta é a
read_text
implementação real :fonte
Bem, se você precisar ler o arquivo linha por linha para trabalhar com cada linha, poderá usar
Ou ainda melhor:
fonte
Em vez de recuperar o conteúdo do arquivo como uma única sequência, pode ser útil armazenar o conteúdo como uma lista de todas as linhas que o arquivo compreende :
Como pode ser visto, é necessário adicionar os métodos concatenados
.strip().split("\n")
à resposta principal neste tópico .Aqui,
.strip()
apenas remove os caracteres de espaço em branco e nova linha nas terminações de toda a cadeia de arquivos e.split("\n")
produz a lista real dividindo a cadeia de arquivos inteira em cada caractere de nova linha \ n .Além disso, dessa forma, todo o conteúdo do arquivo pode ser armazenado em uma variável, o que pode ser desejado em alguns casos, em vez de fazer um loop sobre o arquivo linha por linha, como apontado nesta resposta anterior .
fonte