Tente fileinputcomo descrito por @ jf-sebastian aqui . Parece permitir que você trabalhe linha por linha, através de um arquivo temporário, tudo com uma forsintaxe simples .
Kevin
Respostas:
205
Primeiro, abra o arquivo e obtenha todas as suas linhas. Em seguida, reabra o arquivo no modo de gravação e escreva suas linhas de volta, exceto a linha que você deseja excluir:
with open("yourfile.txt","r")as f:
lines = f.readlines()with open("yourfile.txt","w")as f:for line in lines:if line.strip("\n")!="nickname_to_delete":
f.write(line)
Você precisa strip("\n")do caractere de nova linha na comparação, porque se o arquivo não terminar com um caractere de nova linha, o último linetambém não.
@ Ooker: Você precisa abrir o arquivo duas vezes (e fechá-lo no meio) porque no primeiro modo é "somente leitura" porque você está apenas lendo as linhas atuais do arquivo. Em seguida, feche-o e abra-o novamente no "modo de gravação", onde o arquivo é gravável e você substitui o conteúdo do arquivo sem a linha que deseja remover.
Devin
4
Por que o Python não nos permite fazer isso em uma linha?
Ooker
5
@Ooker, Ao ler uma linha, tente imaginar um cursor se movendo ao longo da linha enquanto é lido. Uma vez que essa linha tenha sido lida, o cursor passou para ela. Ao tentar gravar no arquivo, você escreve onde está o cursor atualmente. Ao reabrir o arquivo, você redefine o cursor.
Waddas
4
Use o composto!
precisa saber é o seguinte
101
Solução para esse problema com apenas uma única abertura:
with open("target.txt","r+")as f:
d = f.readlines()
f.seek(0)for i in d:if i !="line you want to remove...":
f.write(i)
f.truncate()
Esta solução abre o arquivo no modo r / w ("r +") e utiliza o recurso de redefinição do ponteiro f e truncar para remover tudo após a última gravação.
Isso funcionou muito bem para mim, pois eu também tinha que usar o lockfile (fcntl). Não consegui encontrar nenhuma maneira de usar o fileinput junto com o fcntl.
Easyrider
1
Seria bom ver alguns efeitos colaterais desta solução.
user1767754
3
Eu não faria isso. Se ocorrer um erro no forloop, você terminará com um arquivo parcialmente substituído, com linhas duplicadas ou uma linha cortada pela metade. Você pode querer f.truncate()logo depois f.seek(0). Dessa forma, se você receber um erro, acabará com um arquivo incompleto. Mas a solução real (se você tiver espaço em disco) é gerar um arquivo temporário e usá-lo os.replace()ou pathlib.Path(temp_filename).replace(original_filename)trocá-lo pelo original depois que tudo tiver sido bem-sucedido.
224 de Boris
Você pode adicionar i.strip('\n') != "line you want to remove..."como mencionado na resposta aceita, que resolveria perfeitamente meu problema. Porque simplesmente inão fez nada por mim
Mangohero1 06/04
31
A melhor e mais rápida opção, em vez de armazenar tudo em uma lista e reabrir o arquivo para gravá-lo, é na minha opinião reescrever o arquivo em outro lugar.
with open("yourfile.txt","r")as input:with open("newfile.txt","w")as output:for line in input:if line.strip("\n")!="nickname_to_delete":
output.write(line)
É isso aí! Em um loop e apenas um, você pode fazer a mesma coisa. Será muito mais rápido.
Em vez de usar o normal para loop, podemos fazer uso da expressão Generator. Dessa forma, o programa não carrega todas as linhas do arquivo para a memória, o que não é uma boa ideia no caso de arquivos grandes. Ele terá apenas uma linha na memória de cada vez. Com a expressão do gerador, o loop será parecido com,(output.write(line) for line in input if line!="nickname_to_delete"+"\n")
shrishinde 25/02
4
@ShriShinde Você também não está lendo o arquivo na memória ao fazer um loop sobre o objeto de arquivo, portanto esta solução funciona da mesma maneira que a sua sugestão.
Steinar Lima 27/02
Você pode querer excluir o arquivo original e mudar o nome do segundo arquivo ao nome do arquivo original, que com Python em um sistema operacional Linux seria algo como isto,subprocess.call(['mv', 'newfile.txt', 'yourfile.txt'])
Max
6
os.replace(novo no python v 3.3) é mais multiplataforma do que uma chamada de sistema mv.
7yl4r
Simples e ótimo.
JuBaer AD
27
Esta é uma "bifurcação" da resposta do @Lother (que eu acredito que deve ser considerada a resposta certa).
Para um arquivo como este:
$ cat file.txt
1: october rust
2: november rain
3: december snow
Este garfo da solução Lother funciona bem:
#!/usr/bin/python3.4with open("file.txt","r+")as f:
new_f = f.readlines()
f.seek(0)for line in new_f:if"snow"notin line:
f.write(line)
f.truncate()
Melhorias:
with open, que descartam o uso de f.close()
mais claro if/elsepara avaliar se a string não está presente na linha atual
@yifan yes. Caso contrário, em vez de substituir o arquivo, você o anexará (sem as linhas excluídas).
Boris
5
O problema com a leitura de linhas na primeira passagem e a alteração (exclusão de linhas específicas) na segunda passagem é que, se o tamanho dos arquivos for grande, a memória ficará sem RAM. Em vez disso, uma abordagem melhor é ler as linhas, uma a uma, e gravá-las em um arquivo separado, eliminando as que você não precisa. Eu executei essa abordagem com arquivos de 12 a 50 GB e o uso da RAM permanece quase constante. Somente os ciclos da CPU mostram o processamento em andamento.
Esta solução não é independente do sistema operacional e, como o OP não especificou um sistema operacional, não há motivo para postar uma resposta específica do Linux.
Steinar Lima 27/02
2
Qualquer um que sugerir o uso de subprocessos para qualquer coisa que possa ser feita apenas com python recebe um voto negativo! E +1 para @SteinarLima ... eu concordo #
Jamie Lindsey
2
Eu acho que se você ler o arquivo em uma lista, faça o que você pode percorrer na lista para procurar o apelido do qual deseja se livrar. Você pode fazer isso de maneira muito eficiente sem criar arquivos adicionais, mas precisará gravar o resultado novamente no arquivo de origem.
Aqui está como eu poderia fazer isso:
import, os, csv # and other imports you need
nicknames_to_delete =['Nick','Stephen','Mark']
Estou assumindo que nicknames.csvcontém dados como:
Em seguida, itere na lista para corresponder às suas entradas a serem excluídas:
for nick in nicknames_to_delete:try:if nick in nicknames:
nicknames.pop(nicknames.index(nick))else:print(nick +" is not found in the file")exceptValueError:pass
Por fim, escreva o resultado novamente no arquivo:
with open("nicknames.csv","a")as nicknamesFile:
nicknamesFile.seek(0)
nicknamesFile.truncate()
nicknamesWriter = csv.writer(nicknamesFile)for name in nicknames:
nicknamesWriter.writeRow([str(name)])
nicknamesFile.close()
Em geral, você não pode; você precisa escrever o arquivo inteiro novamente (pelo menos do ponto de alteração até o final).
Em alguns casos específicos, você pode fazer melhor que isso -
se todos os seus elementos de dados tiverem o mesmo comprimento e não em uma ordem específica, e você souber o deslocamento daquele que deseja se livrar, copie o último item sobre o que será excluído e trunque o arquivo antes do último item ;
ou você pode simplesmente sobrescrever o bloco de dados com um valor 'são dados incorretos, ignorar' ou manter um sinalizador 'este item foi excluído' nos elementos de dados salvos, para que você possa marcá-lo como excluído sem modificar o arquivo.
Provavelmente isso é um exagero para documentos curtos (algo abaixo de 100 KB?).
Provavelmente, você já obteve uma resposta correta, mas aqui está a minha. Em vez de usar uma lista para coletar dados não filtrados (que readlines()método faz), eu uso dois arquivos. Um é para reter os dados principais e o segundo é para filtrar os dados quando você exclui uma sequência específica. Aqui está um código:
main_file = open('data_base.txt').read()# your main dataBase file
filter_file = open('filter_base.txt','w')
filter_file.write(main_file)
filter_file.close()
main_file = open('data_base.txt','w')for line in open('filter_base'):if'your data to delete'notin line:# remove a specific string
main_file.write(line)# put all strings back to your db except deletedelse:pass
main_file.close()
Salve as linhas do arquivo em uma lista, remova da lista a linha que deseja excluir e grave as linhas restantes em um novo arquivo
with open("file_name.txt","r")as f:
lines = f.readlines()
lines.remove("Line you want to delete\n")with open("new_file.txt","w")as new_f:for line in lines:
new_f.write(line)
Se o seu arquivo não terminar com uma nova linha, esse código não removerá a última linha, mesmo que contenha a palavra que você deseja remover.
Boris
0
Aqui está outro método para remover uma / algumas linhas de um arquivo:
src_file = zzzz.txt
f = open(src_file,"r")
contents = f.readlines()
f.close()
contents.pop(idx)# remove the line item from list, by line number, starts from 0
f = open(src_file,"w")
contents ="".join(contents)
f.write(contents)
f.close()
Supondo que você seja capaz de carregar seu arquivo txt completo. Você define uma lista de apelidos indesejados e os substitui por uma sequência vazia "".
# Delete unwanted charactersimport re
# Read, then decode for py2 compat.
path_to_file ='data/nicknames.txt'
text = open(path_to_file,'rb').read().decode(encoding='utf-8')# Define unwanted nicknames and substitute them
unwanted_nickname_list =['SourDough']
text = re.sub("|".join(unwanted_nickname_list),"", text)
não há necessidade de construir um ditado, basta usarfor nb, line in enumerate(f.readlines())
Dionys
-3
Pegue o conteúdo do arquivo, divida-o por nova linha em uma tupla. Em seguida, acesse o número da linha da sua tupla, junte a tupla de resultado e substitua no arquivo.
(1) você quer dizer tuple(f.read().split('\n'))? (2) "acesse o número da linha da sua tupla" e "junte-se à tupla de resultado" soa bastante misterioso; código Python real pode ser mais compreensível.
fileinput
como descrito por @ jf-sebastian aqui . Parece permitir que você trabalhe linha por linha, através de um arquivo temporário, tudo com umafor
sintaxe simples .Respostas:
Primeiro, abra o arquivo e obtenha todas as suas linhas. Em seguida, reabra o arquivo no modo de gravação e escreva suas linhas de volta, exceto a linha que você deseja excluir:
Você precisa
strip("\n")
do caractere de nova linha na comparação, porque se o arquivo não terminar com um caractere de nova linha, o últimoline
também não.fonte
Solução para esse problema com apenas uma única abertura:
Esta solução abre o arquivo no modo r / w ("r +") e utiliza o recurso de redefinição do ponteiro f e truncar para remover tudo após a última gravação.
fonte
for
loop, você terminará com um arquivo parcialmente substituído, com linhas duplicadas ou uma linha cortada pela metade. Você pode quererf.truncate()
logo depoisf.seek(0)
. Dessa forma, se você receber um erro, acabará com um arquivo incompleto. Mas a solução real (se você tiver espaço em disco) é gerar um arquivo temporário e usá-loos.replace()
oupathlib.Path(temp_filename).replace(original_filename)
trocá-lo pelo original depois que tudo tiver sido bem-sucedido.i.strip('\n') != "line you want to remove..."
como mencionado na resposta aceita, que resolveria perfeitamente meu problema. Porque simplesmentei
não fez nada por mimA melhor e mais rápida opção, em vez de armazenar tudo em uma lista e reabrir o arquivo para gravá-lo, é na minha opinião reescrever o arquivo em outro lugar.
É isso aí! Em um loop e apenas um, você pode fazer a mesma coisa. Será muito mais rápido.
fonte
(output.write(line) for line in input if line!="nickname_to_delete"+"\n")
subprocess.call(['mv', 'newfile.txt', 'yourfile.txt'])
os.replace
(novo no python v 3.3) é mais multiplataforma do que uma chamada de sistemamv
.Esta é uma "bifurcação" da resposta do @Lother (que eu acredito que deve ser considerada a resposta certa).
Para um arquivo como este:
Este garfo da solução Lother funciona bem:
Melhorias:
with open
, que descartam o uso def.close()
if/else
para avaliar se a string não está presente na linha atualfonte
O problema com a leitura de linhas na primeira passagem e a alteração (exclusão de linhas específicas) na segunda passagem é que, se o tamanho dos arquivos for grande, a memória ficará sem RAM. Em vez disso, uma abordagem melhor é ler as linhas, uma a uma, e gravá-las em um arquivo separado, eliminando as que você não precisa. Eu executei essa abordagem com arquivos de 12 a 50 GB e o uso da RAM permanece quase constante. Somente os ciclos da CPU mostram o processamento em andamento.
fonte
Gostei da abordagem fileinput, conforme explicado nesta resposta: Excluindo uma linha de um arquivo de texto (python)
Digamos, por exemplo, que eu tenho um arquivo com linhas vazias e quero remover linhas vazias, eis como eu o resolvi:
fonte
Se você usa Linux, pode tentar a seguinte abordagem.
Suponha que você tenha um arquivo de texto chamado
animal.txt
:Exclua a primeira linha:
então
fonte
Eu acho que se você ler o arquivo em uma lista, faça o que você pode percorrer na lista para procurar o apelido do qual deseja se livrar. Você pode fazer isso de maneira muito eficiente sem criar arquivos adicionais, mas precisará gravar o resultado novamente no arquivo de origem.
Aqui está como eu poderia fazer isso:
Estou assumindo que
nicknames.csv
contém dados como:Em seguida, carregue o arquivo na lista:
Em seguida, itere na lista para corresponder às suas entradas a serem excluídas:
Por fim, escreva o resultado novamente no arquivo:
fonte
Em geral, você não pode; você precisa escrever o arquivo inteiro novamente (pelo menos do ponto de alteração até o final).
Em alguns casos específicos, você pode fazer melhor que isso -
se todos os seus elementos de dados tiverem o mesmo comprimento e não em uma ordem específica, e você souber o deslocamento daquele que deseja se livrar, copie o último item sobre o que será excluído e trunque o arquivo antes do último item ;
ou você pode simplesmente sobrescrever o bloco de dados com um valor 'são dados incorretos, ignorar' ou manter um sinalizador 'este item foi excluído' nos elementos de dados salvos, para que você possa marcá-lo como excluído sem modificar o arquivo.
Provavelmente isso é um exagero para documentos curtos (algo abaixo de 100 KB?).
fonte
Provavelmente, você já obteve uma resposta correta, mas aqui está a minha. Em vez de usar uma lista para coletar dados não filtrados (que
readlines()
método faz), eu uso dois arquivos. Um é para reter os dados principais e o segundo é para filtrar os dados quando você exclui uma sequência específica. Aqui está um código:Espero que você ache isso útil! :)
fonte
Salve as linhas do arquivo em uma lista, remova da lista a linha que deseja excluir e grave as linhas restantes em um novo arquivo
fonte
Aqui está outro método para remover uma / algumas linhas de um arquivo:
fonte
Eu gosto desse método usando fileinput e o método 'inplace':
É um pouco menos prolixo do que as outras respostas e é rápido o suficiente para
fonte
Supondo que você seja capaz de carregar seu arquivo txt completo. Você define uma lista de apelidos indesejados e os substitui por uma sequência vazia "".
fonte
Para excluir uma linha específica de um arquivo pelo seu número de linha :
Substitua variáveis filename e line_to_delete pelo nome do seu arquivo e o número da linha que você deseja excluir.
Exemplo de saída :
fonte
for nb, line in enumerate(f.readlines())
Pegue o conteúdo do arquivo, divida-o por nova linha em uma tupla. Em seguida, acesse o número da linha da sua tupla, junte a tupla de resultado e substitua no arquivo.
fonte
tuple(f.read().split('\n'))
? (2) "acesse o número da linha da sua tupla" e "junte-se à tupla de resultado" soa bastante misterioso; código Python real pode ser mais compreensível.