Disons que j'ai un fichier texte rempli de surnoms. Comment puis-je supprimer un pseudo spécifique de ce fichier, en utilisant Python ?
Pourquoi devons-nous l'ouvrir et le fermer deux fois ?
Disons que j'ai un fichier texte rempli de surnoms. Comment puis-je supprimer un pseudo spécifique de ce fichier, en utilisant Python ?
Tout d'abord, ouvrez le fichier et récupérez toutes vos lignes dans le fichier. Ensuite, rouvrez le fichier en mode écriture et réécrivez vos lignes, à l'exception de celle que vous voulez supprimer :
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)
Vous devez strip("\n")
le caractère de fin de ligne dans la comparaison, car si votre fichier ne se termine pas par un caractère de fin de ligne, le tout dernier caractère de fin de ligne de votre fichier sera utilisé. line
ne le fera pas non plus.
@Ooker : Vous devez ouvrir le fichier deux fois (et le fermer entre les deux) car dans le premier mode, il est en "lecture seule" car vous ne faites que lire les lignes actuelles du fichier. Vous le fermez ensuite et le rouvrez en "mode écriture", où le fichier est accessible en écriture et vous remplacez le contenu du fichier sans la ligne que vous vouliez supprimer.
Solution à ce problème avec une seule ouverture :
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()
Cette solution ouvre le fichier en mode r/w ("r+") et utilise seek pour réinitialiser le f-pointer puis truncate pour supprimer tout ce qui se trouve après la dernière écriture.
Cela a très bien fonctionné pour moi, car j'ai dû utiliser lockfile également (fcntl). Je n'ai pas trouvé de moyen d'utiliser fileinput en même temps que fcntl.
Je ne ferais pas ça. Si vous obtenez une erreur dans le for
vous vous retrouverez avec un fichier partiellement écrasé, avec des lignes en double ou une ligne à moitié coupée. Vous pourriez vouloir f.truncate()
juste après f.seek(0)
à la place. De cette façon, si vous obtenez une erreur, vous vous retrouverez simplement avec un fichier incomplet. Mais la vraie solution (si vous avez l'espace disque nécessaire) est d'effectuer la sortie dans un fichier temporaire, puis d'utiliser la fonction os.replace()
ou pathlib.Path(temp_filename).replace(original_filename)
pour l'échanger avec l'original après que tout ait réussi.
La meilleure option et la plus rapide, plutôt que de tout stocker dans une liste et de rouvrir le fichier pour l'écrire, est à mon avis de réécrire le fichier ailleurs.
with open("yourfile.txt", "r") as file_input:
with open("newfile.txt", "w") as output:
for line in file_input:
if line.strip("\n") != "nickname_to_delete":
output.write(line)
C'est ça ! En une boucle et une seule, vous pouvez faire la même chose. Ce sera beaucoup plus rapide.
Au lieu d'utiliser une boucle for normale, nous pouvons utiliser la méthode suivante Expression du générateur De cette façon, le programme ne chargera pas toutes les lignes du fichier en mémoire, ce qui n'est pas une bonne idée dans le cas de gros fichiers. Il n'aura qu'une seule ligne en mémoire à la fois. Avec l'expression du générateur, la boucle for ressemblera à ceci (output.write(line) for line in input if line!="nickname_to_delete"+"\n")
@ShriShinde Vous ne lisez pas non plus le fichier en mémoire lorsque vous bouclez sur l'objet fichier, donc cette solution fonctionne de manière identique à votre suggestion.
Vous pouvez supprimer le fichier original et renommer le second fichier au nom du fichier original, ce qui, avec Python sur un système d'exploitation Linux, ressemblerait à ceci, subprocess.call(['mv', 'newfile.txt', 'yourfile.txt'])
Il s'agit d'une "bifurcation" de @Lother (qui, à mon avis, devrait être considérée comme la bonne réponse).
Pour un fichier comme celui-ci :
$ cat file.txt
1: october rust
2: november rain
3: december snow
Cette dérivation de la solution de Lother fonctionne bien :
#!/usr/bin/python3.4
with open("file.txt","r+") as f:
new_f = f.readlines()
f.seek(0)
for line in new_f:
if "snow" not in line:
f.write(line)
f.truncate()
Améliorations :
with open
qui rejettent l'utilisation de f.close()
if/else
pour évaluer si la chaîne n'est pas présente dans la ligne couranteLe problème de la lecture des lignes au premier passage et des modifications (suppression de lignes spécifiques) au second passage est que si la taille de votre fichier est énorme, vous manquerez de RAM. Au lieu de cela, une meilleure approche est de lire les lignes, une par une, et de les écrire dans un fichier séparé, en éliminant celles dont vous n'avez pas besoin. J'ai utilisé cette approche avec des fichiers de 12 à 50 Go, et l'utilisation de la RAM reste presque constante. Seuls les cycles du processeur indiquent que le traitement est en cours.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
1 votes
Essayez
fileinput
comme décrit par @j-f-sebastian aquí . Il semble vous permettre de travailler ligne par ligne, via un fichier temporaire, le tout avec une simplefor
la syntaxe.