La lettura di specifiche linee solo

Sto usando un ciclo for per leggere un file, ma io voglio solo leggere linee specifiche, dire la riga #26 e #30. C’è qualche funzione integrata per realizzare questo?

Grazie

InformationsquelleAutor 3zzy | 2010-01-17

 

25 Replies
  1. 234

    Se il file da leggere è grande, e non si vuole leggere l’intero file in memoria in una sola volta:

    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()

    Nota che i == n-1 per il nesima riga.


    In Python 2.6 o versione successiva:

    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
    • +1 soluzione Migliore di quella del mio se il file non viene caricato in memoria, come in linecache. Sei sicuro che enumerate(fp) non farlo?
    • enumerate(x) utilizza x.next, in modo da non avere bisogno di un intero file in memoria.
    • Il mio piccolo di manzo con questo è che Si desidera utilizzare con invece di aprire / chiudere la coppia e quindi mantenere il corpo corto, B), Ma il corpo non è corto. Suona come un trade-off tra velocità/spazio ed essere Divinatori. Io non sono sicuro di quale sia la soluzione migliore potrebbe essere.
    • Grande. Mi piace per quel preciso motivo. Vorrei aggiungere un link alla tua risposta, nel mio.
    • è sopravvalutato, python ha un buon rapporto per più di 13 anni senza di esso
    • Dal momento che questo è da ” 10 e IDK quando io è stato aggiunto, qualcuno può commentare come se uno deve semplice utilizzo per la lettura in un flusso v io.open?
    • è un alias per open. open() funzionerà senza problemi.
    • D. fornitura di energia Elettrica è sopravvalutato, l’umanità ha un buon rapporto per oltre 200 mila anni senza di esso. 😉 ‘con’ sta rendendolo più sicuro, più leggibile, e una linea più breve.
    • perché utilizzare per il ciclo, non credo di poter capire il significato di big file. Il ciclo vorranno anni per raggiungere l’indice

  2. 137

    La risposta rapida:

    f=open('filename')
    lines=f.readlines()
    print lines[25]
    print lines[29]

    o:

    lines=[25, 29]
    i=0
    f=open('filename')
    for line in f:
        if i in lines:
            print i
        i+=1

    C’è una soluzione più elegante per l’estrazione di molte linee: linecache (per gentile concessione di “python: come saltare una riga in un enorme file di testo?”, di un precedente stackoverflow.com domanda).

    Citando la documentazione di python linkato sopra:

    >>> import linecache
    >>> linecache.getline('/etc/passwd', 4)
    'sys:x:3:3:sys:/dev:/bin/sh\n'

    Modificare il 4 il numero di riga, e siete sulla. Notare che il 4 sarebbe portare la quinta riga il conteggio è a base zero.

    Se il file potrebbe essere di grandi dimensioni, e causare problemi durante la lettura in memoria, potrebbe essere una buona idea di prendere @Alok consigli e utilizzare enumerare().

    Per Concludere:

    • Utilizzare fileobject.readlines() o for line in fileobject come una soluzione rapida per i file di piccole dimensioni.
    • Utilizzare linecache per una soluzione più elegante, che sarà abbastanza veloce per la lettura di molti file, possibile più volte.
    • Prendere @Alok il consiglio di usare enumerare() per i file che potrebbe essere molto grande, e non è adatta in memoria. Nota che questo metodo potrebbe rallentare perché il file viene letto in modo sequenziale.
    • Bello. Ho appena guardato la fonte di linecache modulo, e guarda come si legge l’intero file in memoria. Così, se ad accesso casuale è più importante di ottimizzazione delle dimensioni, linecache è il metodo migliore.
    • Grazie per le opzioni! 🙂
    • La soluzione ha un off da un errore, btw 🙂
    • Grazie, risolto.
    • con linecache.getlin(‘nome_file’, 4) ho la linea 4, non 5.
    • fun fact: se si utilizza un insieme invece di lista nel secondo esempio, che si ottiene O(1) tempo di esecuzione. Consulta l’elenco è O(n). Imposta internamente sono rappresentati come hash, ed ecco perché si ottiene O(1) tempo di esecuzione. non è un grosso problema, in questo esempio, ma Se si utilizza un ampio elenco di numeri, di cura e di efficienza, quindi imposta sono il modo migliore per andare.
    • linecache ora sembra funzionare solo per python file di origine

  3. 27

    Rapido e compatto approccio potrebbe essere:

    def picklines(thefile, whatlines):
      return [x for i, x in enumerate(thefile) if i in whatlines]

    questo accetta qualsiasi file aperto-come oggetto thefile (lasciando fino al chiamante se deve essere aperto da un file su disco, o tramite e.g una presa, o altri file come stream) e un insieme di zero-based linea indici whatlines, e restituisce una lista con bassa occupazione di memoria e di velocità ragionevole. Se il numero di righe da restituire è enorme, si potrebbe preferire un generatore:

    def yieldlines(thefile, whatlines):
      return (x for i, x in enumerate(thefile) if i in whatlines)

    che è fondamentalmente solo un bene per il looping su — nota che l’unica differenza viene dal usando arrotondati piuttosto che le parentesi quadre nel return istruzione, di fare un elenco di comprensione e di un generatore di espressione, rispettivamente.

    Ulteriore nota che, nonostante la menzione delle “linee” e “file”, queste funzioni sono molto, molto più generale — lavoreranno sui qualsiasi iterable, sia esso un file aperto o di qualsiasi altro, la restituzione di un elenco (o generatore) di elementi in base al loro progressivo elemento numeri. Quindi, vorrei suggerire l’uso più appropriato generale nomi;-).

    • Io non sono d’accordo — il genexp legge senza problemi e perfettamente.
    • Eccellente ed elegante soluzione, grazie! Infatti, anche file di grandi dimensioni deve essere sostenuto, con il generatore di espressioni. Non può ottenere più elegante di questo, si può? 🙂
    • Bella soluzione, come si può paragonare a quello proposto da @AdamMatan? Adam soluzione potrebbe essere più veloce in quanto sfrutta ulteriori informazioni (numeri di riga monotona crescente) che potrebbe portare ad un precoce stop. Ho 10GB di file che non riesce a caricare in memoria.
    • Non è sottolineato abbastanza, in questa risposta, ma whatlines dovrebbe essere un set, perché if i in whatlines verrà eseguito più velocemente con un set piuttosto che una (ordinati) elenco. Non ho notato per la prima volta e invece ideato la mia brutta soluzione con la lista ordinata (dove non ho dovuto eseguire la scansione di un elenco di ogni tempo, mentre if i in whatlines non solo quello), ma la differenza di prestazioni è trascurabile (con i miei dati) e questa soluzione è molto più elegante.
  4. 26

    Per il bene di offrire un’altra soluzione:

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

    Spero che questo è facile e veloce 🙂

    • Spero che questo è più di una soluzione ottimale .
    • Questa legge l’intero file in memoria. Si potrebbe anche chiamare il file.read().split(‘\n’) e poi utilizzare un indice di array ricerche per ottenere la linea di interesse…
    • Potrebbe dare un esempio di @duhaime
    • Sicuro: gist.github.com/duhaime/4f5f8671e0a752172e4d00f369342361
  5. 14

    se si desidera che la linea 7

    linea = open("file.txt", "r").readlines()[7] 
    
    • Neat. Ma come si fa a close() il file quando si apre in questo modo?
    • abbiamo bisogno di chiudere?
    • sì. abbiamo bisogno di chiudere dopo questo.Quando si apre un file utilizzando “con” … si chiude in sé.
  6. 9

    Per completezza, qui è una opzione in più.

    Cominciamo con una definizione da python-docs:

    fetta Un oggetto che di solito contiene una parte di una sequenza. Una sezione è creata usando l’indice di notazione, [] con i due punti tra numeri diversi sono date, come in nome_variabile[1:3:5]. La staffa (pedice) notazione utilizza oggetti porzione internamente (o nelle versioni precedenti, __getslice__() e __setslice__()).

    Anche se la fetta di notazione non è direttamente applicabile agli iteratori in generale, il itertools pacchetto contiene una funzione di sostituzione:

    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

    Il vantaggio aggiuntivo di una funzione è che non legge l’iteratore fino alla fine. Così si possono fare cose più complesse:

    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

    E per rispondere alla domanda originale:

    # how to read lines #26 and #30
    In [365]: list(islice(xrange(1,100), 25, 30, 4))
    Out[365]: [26, 30]
    • Di gran lunga il miglior approccio quando si lavora con file di grandi dimensioni. Il mio programma è andato dal consumo di 8GB+ a quasi nulla. Il tradoff è stato l’utilizzo della CPU che è andato da ~15% ~40%, ma l’elaborazione vera e propria del file è stato più veloce del 70%. Mi prendo tradoff tutto il giorno. Grazie a te! 🎉🎉🎉
    • Questo mi sembra il più divinatori per me. Grazie!
  7. 9

    La lettura dei file è incredibilmente veloce. La lettura di un file di 100MB prende meno di 0,1 secondi (vedere il mio articolo Lettura e Scrittura di File con Python). Quindi non si dovrebbe leggere completamente e poi lavorare con le singole linee.

    Cosa più risposta qui non è sbagliato, ma un cattivo stile. Apertura di file deve essere sempre fatto con con come si fa in modo che il file viene chiuso di nuovo.

    Così si dovrebbe fare così:

    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

    File di grandi dimensioni

    Se vi capita di avere un file di grandi dimensioni e il consumo di memoria è un problema, è in grado di elaborare linea per linea:

    with open("path/to/file.txt") as f:
        for i, line in enumerate(f):
            pass  # process line i
    • Oh, grazie! Ho risolto.
    • IMO è davvero un cattivo stile di leggere un intero file di unknown lunghezza, solo per ottenere i primi 30 righe .. che cosa è il consumo di memoria .. e di ciò che sta interminabili?
    • Dipende molto dal tipo di applicazione. Per molti, è totalmente bene pensare che un file di testo è un modo di taglia inferiore rispetto alla quantità di memoria disponibile. Se vi capita di avere potenzialmente enormi file, ho modificato la mia risposta.
    • grazie per l’aggiunta, che è lo stesso come alok risposta. E no mi dispiace, non credo che questo dipende dall’applicazione. IMO è sempre meglio non leggere più righe di cui hai bisogno.
  8. 6

    Alcune di queste sono belle, ma si può fare molto più semplicemente:

    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)

    Che utilizzare un semplice elenco di taglio, si carica tutto il file, ma la maggior parte dei sistemi per ridurre al minimo l’utilizzo della memoria in modo appropriato, è più veloce rispetto alla maggior parte dei metodi di cui sopra, e funziona sul mio 10G+ file di dati. Buona fortuna!

  9. 3

    Si può fare un seek() chiamata posizioni che la tua testa di lettura di un byte specificata all’interno del file. Questo non vi aiuterà se non si sa esattamente quanti byte (caratteri) vengono scritti nel file prima della riga che si desidera leggere. Forse il tuo file è strettamente formattato (ogni riga è un numero X di byte?) oppure, si può contare il numero di caratteri di te (ricordati di includere caratteri invisibili come le interruzioni di riga) se si vuole veramente il boost di velocità.

    In caso contrario, è necessario leggere ogni riga prima della riga che si voglia, come per una delle molte soluzioni già proposto qui.

  10. 2

    Come questo:

    >>> 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()
    • Vero, questo è meno efficiente rispetto a quello da Alok, ma la mia utilizza una con dichiarazione 😉
  11. 2

    Se non ti dispiace l’importazione quindi fileinput fa esattamente che cosa avete bisogno (questo è che si può leggere la riga numero di riga corrente)

  12. 2
    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
    • Roger, il mio ragazzo preferito! Questo potrebbe beneficiare di una istruzione.
  13. 2

    Io preferisco questo approccio perché è più general-purpose, cioè si può utilizzare su un file, sul risultato di f.readlines(), su un StringIO oggetto, qualunque:

    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']
  14. 2

    Ecco il mio piccolo di 2 centesimi, per quello che vale 😉

    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])
  15. 2

    Una migliore e modifica minore per Alok Singhal risposta

    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()
  16. 1

    @OP, è possibile utilizzare enumerare

    for n,line in enumerate(open("file")):
        if n+1 in [26,30]: # or n in [25,29] 
           print line.rstrip()
  17. 1
    file = '/path/to/file_to_be_read.txt'
    with open(file) as f:
        print f.readlines()[26]
        print f.readlines()[30]

    Con l’istruzione, questo apre il file, stampe a righe 26 e 30, quindi si chiude il file. Semplice!

    • questa non è una risposta valida. dopo la prima chiamata readlines() l’iteratore si esaurisce e la seconda chiamata verrà restituito un elenco vuoto o genera un errore (non ricordo quale)
  18. 1

    Si può fare questo molto semplicemente con questa sintassi che qualcuno ha già detto, ma è di gran lunga il modo più semplice per farlo:

    inputFile = open("lineNumbers.txt", "r")
    lines = inputFile.readlines()
    print (lines[0])
    print (lines[2])
  19. 1

    Per la stampa di linea# 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

    Originale autore: Frank Hofmann

  20. 1

    Se il grande file di testo file è strettamente ben strutturato (che significa che ogni linea ha la stessa lunghezza l), si potrebbe utilizzare per n-esima riga

    with open(file) as f:
        f.seek(n*l)
        line = f.readline()  # please notice the s at the end!
        last_pos = f.tell()

    Disclaimer Questo è solo per i file con la stessa lunghezza!

  21. 1

    Abbastanza facile e veloce.

    Per la stampa di alcune linee in un file di testo. Creare un “lines2print” elenco e quindi
    basta stampare quando l’enumerazione è “in” il lines2print elenco.
    Per sbarazzarsi di extra ‘\n’ utilizzare la linea.strip() o linea.striscia(‘\n’).
    Mi piace “list comprehension” e tenta di utilizzare quando posso.
    Mi piace il “con” metodo per leggere i file di testo al fine di prevenire
    lasciando un file aperto per qualsiasi motivo.

    lines2print = [26,30] # can be a big list and order doesn't matter.
    
    with open("filepath", 'r') as fp:
        [print(x.strip()) for ei,x in enumerate(fp) if ei in lines2print]

    o se la lista è piccolo basta digitare elenco di un elenco nella comprensione.

    with open("filepath", 'r') as fp:
        [print(x.strip()) for ei,x in enumerate(fp) if ei in [26,30]]
  22. 0

    Per la stampa di linea desiderato.
    Per la stampa della riga di sopra/al di sotto di linea richiesta.

    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()

    esecuzione—->dline(“D:\dummy.txt”,6) io.e dline(“percorso del file”, numero_riga, se si desidera che la linea superiore del ricercato linea 1 per abbassare -1 questo è opzionale valore di default sarà preso 0)

  23. -1
    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()
    • questo è come unpythonic, come si arriva.
    • Dà un risultato errato, in quanto non è possibile utilizzare readlines e readline, come ognuno di modificare le attuali leggi di posizione).
    • Mi dispiace per aver trascurato un ENORME errore nel mio primo codice. L’errore è stato corretto e l’attuale codice dovrebbe funzionare come previsto. Grazie per aver sottolineato il mio errore, Roger Pate.
  24. -1

    Penso che questo lavoro

     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]
    • C’erano già una decina di readline metodi quando hai postato questo–aggiunta di un altro aggiunge solo confusione

Lascia un commento