Como abrir um ficheiro com a instrução open with
estou a ver como fazer a entrada e saída de ficheiros em Python. Eu escrevi o seguinte código para ler uma lista de nomes (um por linha) de um arquivo para outro arquivo, ao verificar um nome com os nomes no arquivo e adicionar texto para as ocorrências no arquivo. O código funciona. Poderia ser melhor?
eu queria usar a declaração with open(...
para ambos os ficheiros de entrada e saída, mas não consigo ver como eles podem estar no mesmo bloco, o que significa que eu teria de armazenar o nomes num local temporário.
def filter(txt, oldfile, newfile):
'''\
Read a list of names from a file line by line into an output file.
If a line begins with a particular name, insert a string of text
after the name before appending the line to the output file.
'''
outfile = open(newfile, 'w')
with open(oldfile, 'r', encoding='utf-8') as infile:
for line in infile:
if line.startswith(txt):
line = line[0:len(txt)] + ' - Truly a great person!\n'
outfile.write(line)
outfile.close()
return # Do I gain anything by including this?
# input the name you want to check against
text = input('Please enter the name of a great person: ')
letsgo = filter(text,'Spanish', 'Spanish2')
4 answers
O Python permite colocar várias open()
num único with
. Separem-nos. Seu código seria então:
def filter(txt, oldfile, newfile):
'''\
Read a list of names from a file line by line into an output file.
If a line begins with a particular name, insert a string of text
after the name before appending the line to the output file.
'''
with open(newfile, 'w') as outfile, open(oldfile, 'r', encoding='utf-8') as infile:
for line in infile:
if line.startswith(txt):
line = line[0:len(txt)] + ' - Truly a great person!\n'
outfile.write(line)
# input the name you want to check against
text = input('Please enter the name of a great person: ')
letsgo = filter(text,'Spanish', 'Spanish2')
E não, você não ganha nada colocando um explícito {[[3]} no final da sua função. Você pode usar return
para sair mais cedo, mas você tinha-o no final, e a função vai sair sem ele. (Claro que com funções que devolvem um valor, você usa o return
para especificar o valor a devolver.)
Usando vários open()
itens com with
foi não é suportado no Python 2.5 quando a Declaração with
foi introduzida, ou no Python 2.6, mas é suportado no Python 2.7 e Python 3.1 ou mais recente.
Http://docs.python.org/reference/compound_stmts.html#the-with-statement http://docs.python.org/release/3.1/reference/compound_stmts.html#the-with-statement
Se está a escrever um código que deve ser executado em Python 2.5, 2.6 ou 3.0, anote as declarações with
como as outras respostas sugeridas ou use contextlib.nested
.
Usar blocos aninhados como este,
with open(newfile, 'w') as outfile:
with open(oldfile, 'r', encoding='utf-8') as infile:
# your logic goes right here
with open(newfile, 'w') as outfile:
with open(oldfile, 'r', encoding='utf-8') as infile:
for line in infile:
if line.startswith(txt):
line = line[0:len(txt)] + ' - Truly a great person!\n'
outfile.write(line)
Isto é melhor do que a sua versão porque garante que outfile
será fechado mesmo que o seu código encontre excepções. Obviamente você poderia fazer isso com tentar/finalmente, mas with
é a maneira certa de fazer isso.
Ou, como acabei de aprender, você pode ter vários gerentes de contexto em uma declaração Como descrito por @steveha. Parece-me uma opção melhor do que o ninho.
E para a tua final uma pergunta menor, o retorno não serve a nenhum propósito real. Eu removia-o.
Às Vezes, você pode querer abrir uma quantidade variável de arquivos e tratar cada um o mesmo, você pode fazer isso com contextlib
from contextlib import ExitStack
filenames = [file1.txt, file2.txt, file3.txt]
with open('outfile.txt', 'a') as outfile:
with ExitStack() as stack:
file_pointers = [stack.enter_context(open(file, 'r')) for file in filenames]
for fp in file_pointers:
outfile.write(fp.read())