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

147
demandé sur 3zzy 2010-01-17 20:14:11

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
192
répondu Alok Singhal 2016-04-02 19:00:59

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() ou for 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.
115
répondu Adam Matan 2017-05-23 11:47:31

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; -).

24
répondu Alex Martelli 2010-01-17 18:42:19

pour offrir une autre solution:

import linecache
linecache.getline('Sample.txt', Number_of_Line)

j'espère que c'est rapide et facile :)

24
répondu KingMak 2014-08-18 15:38:19

si vous voulez ligne 7

line = open("file.txt", "r").readlines()[7]
12
répondu MadSc13ntist 2010-10-21 17:07:39

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]
8
répondu newtover 2014-11-24 15:55:52

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!

4
répondu Will 2018-07-03 16:15:37

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
4
répondu Martin Thoma 2018-09-30 15:30:04

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.

3
répondu Roman 2010-01-17 17:26:08

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()
2
répondu Hamish Grubijan 2010-01-17 17:18:45

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)

2
répondu ennuikiller 2010-01-17 17:21:58
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
2
répondu 2010-01-17 17:33:49

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])
2
répondu AWainb 2010-01-19 01:29:25

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()
2
répondu sedic 2015-12-15 08:10:36

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.

http://docs.python.org/library/stdtypes.html#file.readlines

1
répondu Josh Wright 2010-01-17 17:18:33

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']
1
répondu Robert Rossney 2010-01-17 18:37:36

@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()
1
répondu ghostdog74 2010-01-18 00:32:05
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!

1
répondu user3901273 2015-05-17 15:38:08

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

1
répondu crazy_daffodils 2018-09-30 14:39:59

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])
0
répondu Trey50Daniel 2016-02-21 20:48:12

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)

0
répondu sudhir tataraju 2018-08-22 16:38:28

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!

0
répondu Michael Dorner 2018-09-30 15:01:06
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()
-1
répondu inspectorG4dget 2010-01-17 22:53:52

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]
-1
répondu San k 2015-04-10 06:05:04