Lecture de lignes spécifiques seulement (Python)
j'utilise une boucle for pour lire un fichier, mais je ne veux lire que les lignes spécifiques, disons les lignes #26 et #30. Est-il une fonctionnalité intégrée pour y parvenir?
Merci
24 réponses
Si le fichier à lire est grand, et vous ne voulez pas lire tout le fichier en mémoire à la fois:
fp = open("file")
for i, line in enumerate(fp):
if i == 25:
# 26th line
elif i == 29:
# 30th line
elif i > 29:
break
fp.close()
noter que i == n-1
pour la ligne n
.
en Python 2.6 ou plus tard:
with open("file") as fp:
for i, line in enumerate(fp):
if i == 25:
# 26th line
elif i == 29:
# 30th line
elif i > 29:
break
la réponse rapide:
f=open('filename')
lines=f.readlines()
print lines[25]
print lines[29]
ou:
lines=[25, 29]
i=0
f=open('filename')
for line in f:
if i in lines:
print i
i+=1
il y a une solution plus élégante pour extraire de nombreuses lignes: linecache (courtoisie de "python: comment sauter à une ligne particulière dans un fichier texte énorme?" , l'une des précédentes stackoverflow.com question).
citant la documentation python liée ci-dessus:
>>> import linecache
>>> linecache.getline('/etc/passwd', 4)
'sys:x:3:3:sys:/dev:/bin/sh\n'
modifier le 4
à la ligne de votre choix, et c'est parti. Notez que 4 apporterait la cinquième ligne car le compte est basé sur zéro.
si le fichier peut être très volumineux, et causer des problèmes lorsqu'il est lu dans la mémoire, il pourrait être une bonne idée de prendre les conseils de @Alok et d'utiliser enumerate () .
Pour Conclure:
- utiliser
fileobject.readlines()
oufor line in fileobject
comme une solution rapide pour les petits fichier. - utiliser
linecache
pour une solution plus élégante, qui sera assez rapide pour la lecture de nombreux fichiers, possible à plusieurs reprises. - prenez les conseils de @Alok et utilisez
enumerate()
pour les fichiers qui pourraient être très gros, et ne rentreront pas dans la mémoire. Notez que l'utilisation de cette méthode peut ralentir car le fichier est lu séquentiellement.
une approche rapide et compacte pourrait être:
def picklines(thefile, whatlines):
return [x for i, x in enumerate(thefile) if i in whatlines]
accepte tout objet ouvert ressemblant à un fichier thefile
(laissant à l'appelant le choix de savoir s'il doit être ouvert à partir d'un fichier disque, ou via E. g une socket, ou autre flux de type fichier) et un ensemble d'indices de ligne à base zéro whatlines
, et renvoie une liste, avec une faible empreinte mémoire et une vitesse raisonnable. Si le nombre de lignes à retourner est énorme, vous pouvez préférer un générateur:
def yieldlines(thefile, whatlines):
return (x for i, x in enumerate(thefile) if i in whatlines)
, ce qui n'est bon qu'en boucle -- notez que la seule différence vient de l'utilisation de parenthèses arrondies plutôt que carrées dans l'énoncé return
, faisant une compréhension de liste et une expression génératrice respectivement.
notez En outre que malgré la mention de "lignes" et "Fichier" ces fonctions sont beaucoup, beaucoup plus général-ils vont travailler sur n'importe itérable, que ce soit un fichier ouvert ou n'importe autre, retour d'une liste (ou générateur) d'articles en fonction de leurs numéros d'articles progressifs. Donc, je suggère d'utiliser des noms généraux plus appropriés; -).
pour offrir une autre solution:
import linecache
linecache.getline('Sample.txt', Number_of_Line)
j'espère que c'est rapide et facile :)
si vous voulez ligne 7
line = open("file.txt", "r").readlines()[7]
par souci d'exhaustivité, voici une autre option.
commençons par une définition de python docs :
tranche objet contenant habituellement une partie d'une séquence. Une tranche est créée à l'aide de la notation en indice, [] avec des points entre les nombres lorsque plusieurs sont donnés, comme dans NOM_VARIABLE[1:3:5]. La notation bracket (indice) utilise des objets slice en interne (ou dans les versions plus anciennes, __getslice__ () et __setslice__()).
bien que la notation de la tranche ne s'applique pas directement aux itérateurs en général, le paquet itertools
contient une fonction de remplacement:
from itertools import islice
# print the 100th line
with open('the_file') as lines:
for line in islice(lines, 99, 100):
print line
# print each third line until 100
with open('the_file') as lines:
for line in islice(lines, 0, 100, 3):
print line
L'avantage supplémentaire de la fonction, c'est qu'il ne lit pas l'itérateur jusqu'à la fin. Donc vous pouvez faire des choses plus complexes:
with open('the_file') as lines:
# print the first 100 lines
for line in islice(lines, 100):
print line
# then skip the next 5
for line in islice(lines, 5):
pass
# print the rest
for line in lines:
print line
et de répondre à la question initiale:
# how to read lines #26 and #30
In [365]: list(islice(xrange(1,100), 25, 30, 4))
Out[365]: [26, 30]
Certains sont beau, mais il peut être fait beaucoup plus simplement:
start = 0 # some starting index
end = 5000 # some ending index
filename = 'test.txt' # some file we want to use
with open(filename) as fh:
data = fin.readlines()[start:end]
print(data)
qui utilisera simplement le découpage de liste, il charge l'ensemble du fichier, mais la plupart des systèmes minimisera l'utilisation de la mémoire de manière appropriée, il est plus rapide que la plupart des méthodes indiquées ci-dessus, et fonctionne sur mes fichiers de données 10G+. Bonne chance!
lire des fichiers est incroyablement rapide. Lire un fichier de 100 Mo prend moins de 0,1 seconde (voir mon article lire et écrire des fichiers avec Python ). Par conséquent, vous devriez le lire complètement et ensuite travailler avec des lignes simples.
ce que la plupart des réponses ici font n'est pas mal, mais de mauvais style. L'ouverture des fichiers doit toujours être faite avec with
car il s'assure que le fichier est fermé à nouveau.
donc vous devrait le faire comme ceci:
with open("path/to/file.txt") as f:
lines = f.readlines()
print(lines[26]) # or whatever you want to do with this line
print(lines[30]) # or whatever you want to do with this line
gros fichiers
si vous avez un énorme fichier et que la consommation de mémoire est un problème, vous pouvez le traiter ligne par ligne:
with open("path/to/file.txt") as f:
for i, line in enumerate(f):
pass # process line i
vous pouvez faire un appel seek () qui positionne votre tête de lecture à un octet spécifié dans le fichier. Cela ne vous aidera que si vous savez exactement combien d'octets (caractères) sont écrits dans le fichier avant la ligne que vous voulez lire. Peut-être votre fichier est-il strictement formaté (chaque ligne est un nombre X d'octets?) ou, vous pouvez compter le nombre de caractères vous-même (n'oubliez pas d'inclure des caractères invisibles comme les sauts de ligne) si vous voulez vraiment l'augmentation de vitesse.
sinon, vous devez lire chaque ligne avant la ligne que vous désirez, comme selon l'une des nombreuses solutions déjà proposées ici.
Que pensez-vous de ceci:
>>> with open('a', 'r') as fin: lines = fin.readlines()
>>> for i, line in enumerate(lines):
if i > 30: break
if i == 26: dox()
if i == 30: doy()
si cela ne vous dérange pas d'importer alors fileinput fait exactement ce dont vous avez besoin (c'est que vous pouvez lire le numéro de ligne de la ligne courante)
def getitems(iterable, items):
items = list(items) # get a list from any iterable and make our own copy
# since we modify it
if items:
items.sort()
for n, v in enumerate(iterable):
if n == items[0]:
yield v
items.pop(0)
if not items:
break
print list(getitems(open("/usr/share/dict/words"), [25, 29]))
# ['Abelson\n', 'Abernathy\n']
# note that index 25 is the 26th item
Voici ma petite de 2 cents, pour ce que ça vaut la peine ;)
def indexLines(filename, lines=[2,4,6,8,10,12,3,5,7,1]):
fp = open(filename, "r")
src = fp.readlines()
data = [(index, line) for index, line in enumerate(src) if index in lines]
fp.close()
return data
# Usage below
filename = "C:\Your\Path\And\Filename.txt"
for line in indexLines(filename): # using default list, specify your own list of lines otherwise
print "Line: %s\nData: %s\n" % (line[0], line[1])
Une meilleure et changement mineur pour Alok Singhal, la réponse de
fp = open("file")
for i, line in enumerate(fp,1):
if i == 26:
# 26th line
elif i == 30:
# 30th line
elif i > 30:
break
fp.close()
Fichier un des objets .readlines () méthode qui vous donnera une liste du contenu du fichier, une ligne par élément de liste. Après cela, vous pouvez juste utiliser les techniques normales de tranchage de liste.
je préfère cette approche parce que c'est plus général-but, i.e. vous pouvez l'utiliser sur un fichier, sur le résultat de f.readlines()
, sur un StringIO
objet, quoi que:
def read_specific_lines(file, lines_to_read):
"""file is any iterable; lines_to_read is an iterable containing int values"""
lines = set(lines_to_read)
last = max(lines)
for n, line in enumerate(file):
if n + 1 in lines:
yield line
if n + 1 > last:
return
>>> with open(r'c:\temp\words.txt') as f:
[s for s in read_specific_lines(f, [1, 2, 3, 1000])]
['A\n', 'a\n', 'aa\n', 'accordant\n']
@OP, vous pouvez utiliser enumerate
for n,line in enumerate(open("file")):
if n+1 in [26,30]: # or n in [25,29]
print line.rstrip()
file = '/path/to/file_to_be_read.txt'
with open(file) as f:
print f.readlines()[26]
print f.readlines()[30]
en utilisant l'instruction with, ceci ouvre le fichier, imprime les lignes 26 et 30, puis ferme le fichier. Simple!
pour imprimer la ligne 3,
line_number = 3
with open(filename,"r") as file:
current_line = 1
for line in file:
if current_line == line_number:
print(file.readline())
break
current_line += 1
auteur original: Frank Hofmann
vous pouvez le faire très simplement avec cette syntaxe que quelqu'un a déjà mentionnée, mais c'est de loin la façon la plus facile de le faire:
inputFile = open("lineNumbers.txt", "r")
lines = inputFile.readlines()
print (lines[0])
print (lines[2])
Pour imprimer la ligne désirée. Imprimer ligne au-dessus/en-dessous de ligne nécessaires.
def dline(file,no,add_sub=0):
tf=open(file)
for sno,line in enumerate(tf):
if sno==no-1+add_sub:
print(line)
tf.close()
exécuter---->dline("D:\dummy.txt",6) j'.e dline("chemin du fichier", numéro de ligne, si vous voulez la ligne supérieure de la droite cherchée donner 1 pour le bas -1 c'est facultatif, la valeur par défaut sera prise 0)
si votre grand fichier de texte file
est strictement bien structuré (ce qui signifie que chaque ligne a la même longueur l
), vous pouvez utiliser pour n
- TH ligne
with open(file) as f:
f.seek(n*l)
line = f.readline() # please notice the s at the end!
last_pos = f.tell()
Avertissement Cela fonctionne uniquement pour les fichiers avec la même longueur!
f = open(filename, 'r')
totalLines = len(f.readlines())
f.close()
f = open(filename, 'r')
lineno = 1
while lineno < totalLines:
line = f.readline()
if lineno == 26:
doLine26Commmand(line)
elif lineno == 30:
doLine30Commmand(line)
lineno += 1
f.close()
je pense que ce serait le travail
open_file1 = open("E:\test.txt",'r')
read_it1 = open_file1.read()
myline1 = []
for line1 in read_it1.splitlines():
myline1.append(line1)
print myline1[0]