Jak odczytać plik bez znaku nowej linii?

374

W Pythonie dzwonienie

temp = open(filename,'r').readlines()

daje listę, w której każdy element jest linią w pliku. Jest to trochę głupie, ale nadal: readlines()zapisuje także znak nowego wiersza do każdego elementu, czego nie chciałbym wydarzyć.

Jak mogę tego uniknąć?

Yotam
źródło
4
Zastosowanie taśmy: [l.strip('\n\r') for l in temp]. Lub nawet rstrip. A ponieważ iteracja tutaj może być in openzamiast in temp.
gorlum0
11
Byłoby miło, gdyby w Pythonie 3 istniała wartość pozwalająca ustawić newlineargument open na te gryzące końcowe wiersze.
jxramos

Odpowiedzi:

554

Możesz odczytać cały plik i linie podziału za pomocą str.splitlines:

temp = file.read().splitlines()

Lub możesz ręcznie usunąć nową linię:

temp = [line[:-1] for line in file]

Uwaga: to ostatnie rozwiązanie działa tylko wtedy, gdy plik kończy się na nowej linii, w przeciwnym razie ostatnia linia straci znak.

To założenie jest prawdziwe w większości przypadków (szczególnie w przypadku plików utworzonych przez edytorów tekstowych, które często zrobienia dodać kończący znak nowej linii w każdym razie).

Jeśli chcesz tego uniknąć, możesz dodać nowy wiersz na końcu pliku:

with open(the_file, 'r+') as f:
    f.seek(-1, 2)  # go at the end of the file
    if f.read(1) != '\n':
        # add missing newline if not already present
        f.write('\n')
        f.flush()
        f.seek(0)
    lines = [line[:-1] for line in f]

Lub prostszą alternatywą jest stripzamiast nowej linii:

[line.rstrip('\n') for line in file]

Lub nawet, chociaż dość nieczytelne:

[line[:-(line[-1] == '\n') or len(line)+1] for line in file]

Który wykorzystuje fakt, że zwracana wartość ornie jest wartością logiczną, ale obiektem, który został oceniony jako prawda lub fałsz.


readlinesMetoda jest rzeczywiście równoważne:

def readlines(self):
    lines = []
    for line in iter(self.readline, ''):
        lines.append(line)
    return lines

# or equivalently

def readlines(self):
    lines = []
    while True:
        line = self.readline()
        if not line:
            break
        lines.append(line)
    return lines

Ponieważ readline()utrzymuje nową linię, również readlines()ją utrzymuje.

Uwaga: dla symetrii do readlines()tej writelines()metody jest nie dodać kończące znaki nowej linii, więc f2.writelines(f.readlines())tworzy dokładną kopię fw f2.

Bakuriu
źródło
1
Pamiętaj, że [line.rstrip('\n') for line in file]usuniesz więcej niż jeden końcowy \n.
Wes Turner,
1
Mówiąc prościej, [line[:-(line[-1] == '\n') or len(line)+1] for line in file]może zamiast tego być [line[:-(line[-1] == '\n') or None] for line in file].
Wes Turner,
10
Te rozwiązania wczytują cały plik do pamięci. Zmiana nawiasów kwadratowych opisu listy na nawiasy tworzy wyrażenie generujące, które pozwala na iterację po pliku po jednym wierszu na raz: for line in (x.strip() for x in f):
Joseph Sheedy,
2
@velotron To nie jest tak naprawdę pytanie / odpowiedź. Ponadto: pamiętaj, że withzamyka pliki po zakończeniu bloku, co oznacza, że ​​nie możesz tego robić with open(...) as f: lines = (line for line in f)i używać linespoza, withponieważ pojawi się błąd we / wy. Możesz być leniwy, używając genexp, ale musisz go zużyć przed zamknięciem pliku.
Bakuriu
@WesTurner. Ale nie będzie więcej niż jedna nowa linia. Dodatkowa nowa linia będzie częścią następnej pustej linii
Szalony fizyk
38
temp = open(filename,'r').read().split('\n')
vivek
źródło
14
Co by się jednak stało z \r\nnowymi liniami? ;)
Wolph
26
Python automatycznie obsługuje uniwersalne znaki nowej linii, dzięki czemu .split('\n')podzieli się poprawnie, niezależnie od konwencji nowej linii. Miałoby to znaczenie, jeśli czytasz plik w trybie binarnym. W takim przypadku splitlines()obsługuje uniwersalne znaki nowej linii, podczas gdy split('\n')nie.
Bakuriu
7
I zawsze jest os.linesep:)
askewchan
1
@ LarsH, w niektórych przypadkach pomogłoby to, że w moim systemie \r\nzakończenia linii nie są konwertowane \n, czy to czytane jako tekstowe, czy binarne, więc os.linesepdziałałyby tam, gdzie \nnie. Ale splitlinesjest wyraźnie lepszym wyborem, w przypadku, gdy wspominasz, gdzie plik nie pasuje do systemu operacyjnego. Naprawdę wspomniałem o tym głównie na wypadek, gdyby ludzie przyglądający się tej dyskusji nie byli świadomi jej istnienia.
askewchan
1
@askewchan Być może korzystasz z nieaktualnej wersji Pythona. Wierzę, że od Python 3 uniwersalne znaki nowej linii są domyślnie włączone, tzn. \r\nBędą konwertowane na pliki tekstowe, nawet jeśli pracujesz w systemie Linux.
Arthur Tacca,
13

inny przykład:

Odczytywanie pliku po jednym wierszu naraz. Usuwanie niechcianych znaków z końca łańcuchastr.rstrip(chars)

with open(filename, 'r') as fileobj:
    for row in fileobj:
        print( row.rstrip('\n') )

patrz także str.strip([chars])istr.lstrip([chars])

(python> = 2.0)

O-9
źródło
10
temp = open(filename,'r').read().splitlines()
Marcel
źródło
5
Czy jesteś pewien, że to zamyka plik? Myślę, że tak nie jest, więc tak naprawdę nie jest to jedna linijka ...
Ray Hulha
9

Myślę, że to najlepsza opcja.

temp = [line.strip() for line in file.readlines()]
RENZO
źródło
8
To rozwiązanie usuwa również spacje wiodące i końcowe, co nie jest zamierzone.
Roland Illig
Jednak zrozumienie jest naprawdę miłe. Przynajmniej w Pythonie 3 można użyć, temp = [line.rstrip() for line in file.readlines()]aby uzyskać to, co przeznaczone są notatki @Roland_Illig.
bballdave025
Jeśli masz zamiar powtarzać wszystkie linie, dlaczego nie leniwie? Dzięki .readlines(), skutecznie powtarzasz dwukrotnie cały plik.
AMC
1

Spróbuj tego:

u=open("url.txt","r")  
url=u.read().replace('\n','')  
print(url)  
Nitesh Soni
źródło
4
Ten fragment kodu może rozwiązać pytanie, ale wyjaśnienie naprawdę pomaga poprawić jakość posta. Pamiętaj, że w przyszłości odpowiadasz na pytanie czytelników, a ci ludzie mogą nie znać przyczyn Twojej sugestii kodu. Staraj się również nie tłoczyć kodu objaśniającymi komentarzami, ponieważ zmniejsza to czytelność zarówno kodu, jak i objaśnień!
Do widzenia StackExchange
Nie rozumiem, dlaczego ktokolwiek miałby to wykorzystywać w stosunku do niektórych alternatywnych rozwiązań.
AMC
-1
my_file = open("first_file.txt", "r")
for line in my_file.readlines():
    if line[-1:] == "\n":
        print(line[:-1])
    else:
        print(line)
my_file.close() 
Necriss
źródło
3
Dodaj wyjaśnienie, aby było przydatne dla innych.
samuellawrentz
Do obsługi obiektu pliku należy użyć menedżera kontekstu i bezpośrednio iterować plik. Korzystając z .readlines()tego w ten sposób, skutecznie iterujesz dwa razy cały plik.
AMC
-2
import csv

with open(filename) as f:
    csvreader = csv.reader(f)
    for line in csvreader:
         print(line[0])
srus
źródło
2
Ale co jeśli linia zawiera przecinek?
gilch
-8
def getText():
    file=open("ex1.txt","r");

    names=file.read().split("\n");
    for x,word in enumerate(names):
        if(len(word)>=20):
            return 0;
            print "length of ",word,"is over 20"
            break;
        if(x==20):
            return 0;
            break;
    else:
        return names;


def show(names):
    for word in names:
        len_set=len(set(word))
        print word," ",len_set


for i in range(1):

    names=getText();
    if(names!=0):
        show(names);
    else:
        break;
użytkownik4730171
źródło