Najlepsza metoda czytania plików rozdzielanych znakami nowej linii i odrzucania nowych linii?

84

Próbuję określić najlepszy sposób na pozbycie się znaków nowej linii podczas czytania w plikach rozdzielanych znakami nowej linii w Pythonie.

To, co wymyśliłem, to następujący kod, zawiera kod jednorazowy do przetestowania.

import os

def getfile(filename,results):
   f = open(filename)
   filecontents = f.readlines()
   for line in filecontents:
     foo = line.strip('\n')
     results.append(foo)
   return results

blahblah = []

getfile('/tmp/foo',blahblah)

for x in blahblah:
    print x

Propozycje?

solarce
źródło
a co z użyciem podziału („/ n”)?
JLE
1
To samo co: stackoverflow.com/questions/339537/…
Vijay Dev
Myślę, że też lepiej byłoby zamknąć teczkę
Paweł Prażak 08.08.11

Odpowiedzi:

196
lines = open(filename).read().splitlines()
Curt Hagenlocher
źródło
1
Ta odpowiedź robi to, do czego dążyłem, jestem pewien, że będę musiał dodać trochę sprawdzania błędów i tak dalej, ale dla tej konkretnej potrzeby jest świetny. Dziękuję wszystkim za udzielenie odpowiedzi!
solarce
Podoba mi się to, ale jak zamknąć plik, jeśli nie zapisujesz uchwytu pliku? Czy jest automatycznie zamykana?
IJ Kennedy
6
W CPythonie liczba odwołań dla obiektu pliku spadnie do zera, gdy nie będzie już używany, a plik zostanie automatycznie zamknięty. W przypadku implementacji czysto GC, takich jak Jython i IronPython, plik może nie zostać zamknięty do czasu uruchomienia GC - więc ta zwięzła odmiana może nie być optymalna.
Curt Hagenlocher
2
W systemie Mac OS X 10.7.5 z 8 GB pamięci RAM mogę odczytać plik do 2047 MB ​​(moja definicja: 1 MB = 1024 x 1024 bajtów). 2048 MB spowoduje zgłoszenie wyjątku MemoryError.
Hai Vu
1
@WKPlus Doskonałe pytanie - odpowiedź brzmi "to zależy" stackoverflow.com/a/15099341/994153 (CPython zamknie to, ponieważ liczba odwołań spadnie do zera, ale inne implementacje Pythona mogą go nie zamknąć, więc najlepiej jest to wyraźnie określić )
Colin D Bennett
23

Oto generator, który robi to, o co prosiłeś. W takim przypadku użycie rstrip jest wystarczające i nieco szybsze niż strip.

lines = (line.rstrip('\n') for line in open(filename))

Jednak najprawdopodobniej będziesz chciał użyć tego również do pozbycia się końcowych białych znaków.

lines = (line.rstrip() for line in open(filename))
TimoLinna
źródło
Czy nie powinno być [] wokół RHS, a nie ()?
andrewb
8
@andrewb Użycie () daje wyrażenie generatora, które nie zużywa tyle pamięci, co użycie [] (rozumienie listy).
Jonathan Hartley
9

Co myślisz o tym podejściu?

with open(filename) as data:
    datalines = (line.rstrip('\r\n') for line in data)
    for line in datalines:
        ...do something awesome...

Wyrażenie generatora pozwala uniknąć ładowania całego pliku do pamięci i withzapewnia zamknięcie pliku

Paweł Prażak
źródło
To jest w zasadzie taka sama jak @ TimoLinna za odpowiedź wysłane lat wcześniej ...
martineau
8
for line in file('/tmp/foo'):
    print line.strip('\n')
David Z
źródło
4

Po prostu użyj wyrażeń generatora:

blahblah = (l.rstrip() for l in open(filename))
for x in blahblah:
    print x

Chciałbym również odradzić wczytywanie całego pliku w pamięci - pętla nad generatorami jest znacznie wydajniejsza w przypadku dużych zbiorów danych.


źródło
3

używam tego

def cleaned( aFile ):
    for line in aFile:
        yield line.strip()

Wtedy mogę robić takie rzeczy.

lines = list( cleaned( open("file","r") ) )

Lub mogę rozszerzyć funkcję wyczyszczoną o dodatkowe funkcje, na przykład, aby upuścić puste wiersze lub pominąć wiersze komentarzy lub cokolwiek innego.

S.Lott
źródło
2

Zrobiłbym to tak:

f = open('test.txt')
l = [l for l in f.readlines() if l.strip()]
f.close()
print l
S.Lott
źródło
Chociaż odpowiedź Curta Hagenlochera jest technicznie lepsza, to ta odpowiedź jest dobrym punktem wyjścia, jeśli chcesz dodać inne przetwarzanie do każdej linii.
TomOnTime
Nie jestem pewien, czy miał na celu filtrowanie pustych wierszy, ale jest to bardziej zwięzłe niż ... if l.strip() is not '', czego potrzebuję w moim przypadku.
Zach Young,