Por que não consigo usar uma string para uma nova linha em write (), mas posso usá-la em writelines ()?
A idéia é a seguinte: se você deseja escrever uma única string, pode fazê-lo write()
. Se você tiver uma sequência de strings, poderá escrever todas elas usando writelines()
.
write(arg)
espera uma string como argumento e a grava no arquivo Se você fornecer uma lista de strings, isso gerará uma exceção (a propósito, mostre erros para nós!).
writelines(arg)
espera um argumento iterável como (um objeto iterável pode ser uma tupla, uma lista, uma string ou um iterador no sentido mais geral). Espera-se que cada item contido no iterador seja uma sequência. Uma tupla de strings é o que você forneceu, para que as coisas funcionassem.
A natureza das strings não importa para as duas funções, ou seja, elas apenas gravam no arquivo o que você fornecer. A parte interessante é que writelines()
não adiciona caracteres de nova linha por conta própria, portanto o nome do método pode ser bastante confuso. Na verdade, ele se comporta como um método imaginário chamado write_all_of_these_strings(sequence)
.
A seguir, é uma maneira idiomática no Python para escrever uma lista de strings em um arquivo, mantendo cada string em sua própria linha:
lines = ['line1', 'line2']
with open('filename.txt', 'w') as f:
f.write('\n'.join(lines))
Isso cuida do fechamento do arquivo para você. A construção '\n'.join(lines)
concatena (conecta) as seqüências de caracteres na lista lines
e usa o caractere '\ n' como cola. É mais eficiente do que usar o +
operador.
Começando na mesma lines
sequência, terminando com a mesma saída, mas usando writelines()
:
lines = ['line1', 'line2']
with open('filename.txt', 'w') as f:
f.writelines("%s\n" % l for l in lines)
Isso faz uso de uma expressão de gerador e cria dinamicamente seqüências terminadas em nova linha. writelines()
itera sobre essa sequência de strings e grava todos os itens.
Edit: Outro ponto que você deve estar ciente de:
write()
e readlines()
existia antes de writelines()
ser introduzido. writelines()
foi introduzido mais tarde como uma contrapartida de readlines()
, para que se pudesse escrever facilmente o conteúdo do arquivo que acabou de ser lido através de readlines()
:
outfile.writelines(infile.readlines())
Realmente, essa é a principal razão pela qual writelines
esse nome é confuso. Além disso, hoje, realmente não queremos mais usar esse método. readlines()
lê o arquivo inteiro na memória da sua máquina antes de writelines()
começar a gravar os dados. Primeiro de tudo, isso pode perder tempo. Por que não começar a escrever partes dos dados enquanto lê outras partes? Mas, o mais importante, essa abordagem pode consumir muita memória. Em um cenário extremo, onde o arquivo de entrada é maior que a memória da sua máquina, essa abordagem nem funciona. A solução para esse problema é usar apenas iteradores. Um exemplo de trabalho:
with open('inputfile') as infile:
with open('outputfile') as outfile:
for line in infile:
outfile.write(line)
Isso lê o arquivo de entrada linha por linha. Assim que uma linha é lida, essa linha é gravada no arquivo de saída. Esquematicamente falado, sempre há apenas uma única linha na memória (em comparação com todo o conteúdo do arquivo na memória, no caso da abordagem de linhas de leitura / linhas de escrita).
lines
não é uma string no seu exemplo. É uma tupla composta por seis cordas.