Najłatwiejszy sposób na odczyt / zapis zawartości pliku w Pythonie


83

W Rubim możesz czytać z pliku za pomocą s = File.read(filename). Najkrótszy i najbardziej przejrzysty, jaki znam w Pythonie, to

with open(filename) as f:
    s = f.read()

Czy jest jakiś inny sposób, aby to zrobić, aby był jeszcze krótszy (najlepiej jedna linia) i bardziej czytelny?

Uwaga: początkowo sformułowałem pytanie jako „robię to w jednej linii kodu”. Jak zauważył S.Lott, krótszy nie musi oznaczać bardziej czytelnego. Więc przeformułowałem moje pytanie, aby wyjaśnić, co mam na myśli. Myślę, że kod Ruby jest lepszy i bardziej czytelny niekoniecznie dlatego, że jest to jedna linia kontra dwie (choć to też ma znaczenie), ale także dlatego, że jest to metoda klasowa w przeciwieństwie do metody instancji, która nie stawia pytania o to, kto zamyka plik, jak upewnić się, że zostanie zamknięty, nawet jeśli zostanie zgłoszony wyjątek itp. Jak wskazano w poniższych odpowiedziach, możesz polegać na GC, aby zamknąć plik (czyniąc go tym samym jednowierszowym), ale to jeszcze bardziej pogarsza kod chociaż jest krótszy. Nie tylko dlatego, że nie da się go przenosić, ale też czyniąc to niejasnym.


7
Utwórz własną funkcję. Następnie możesz go użyć, aby pobrać zawartość. Połączenie byłoby jedną linią.
Felix Kling

1
Ciekawe, czy instrukcja Ruby również zamyka plik?
dheerosaur

8
-1: Nikt nie wygrywa w Code Golf.
S.Lott,

4
Moje pytanie ma dla mnie sens. Próbuję znaleźć lepszy sposób na zapisanie tych dwóch wierszy (4 wiersze przed withinstrukcją w 2.5). Może jest sposób, może nie ma. Zawsze mogę spróbować się dowiedzieć, prawda? Jeśli ci się to nie podoba, zagłosuj przeciw i przejdź dalej. :)
ibz

1
Zaletą programu File.readlines("filename")jest to, że czyta zawartość pliku, podając jego nazwę. Nigdzie nie ma uchwytu pliku, deskryptora ani obiektu. Wszystkie „odpowiedniki” Pythona, które widziałem, obejmują jawne otwarcie / zamknięcie (lub, co gorsza, niejawne otwarcie, które wymaga jawnego zamknięcia).
Mark Reed,

Odpowiedzi:


12

Jeśli jesteś otwarty na używanie bibliotek, spróbuj zainstalować rozwidloną ścieżkę (z easy_install lub pip).

Następnie możesz:

from path import path
s = path(filename).bytes()

Ta biblioteka jest dość nowa, ale jest to rozwidlenie biblioteki, która od lat unosi się w Pythonie i była dość często używana. Odkąd znalazłem tę bibliotekę lata temu, bardzo rzadko używam os.pathlub w open()ogóle.


Wygląda na niezłą bibliotekę. Nie zainstaluję tego tylko w tym celu, ale będę o tym pamiętać.
ibz

1
Nie rozumiem, dlaczego była to akceptowana odpowiedź, ponieważ to totalny hack!
nikolay

Wersja forked-path v0.2.3 zainstalowana przez pip 18.6 w systemie Windows nie jest zgodna z Pythonem 3.6.4. Wygląda na to, że format używany dla stałych ósemkowych (np. 0777Zamiast 0o0777) nie jest obsługiwany przez moją obecną wersję Pythona.
Christoffer Soop

+1 do odpowiedzi Eyala Levina . Gdyby pathlib lub pathlib2 istniały, kiedy pierwotnie odpowiadałem na to 8 lat temu, wspomniałbym o nich, a nie forked-path. Od lat nie korzystałem z rozwidlonej ścieżki.
snapshoe

151
with open('x.py') as f: s = f.read()

*** uśmiecha się ***


1
Po prostu nie ma powodu, aby nie pisać tego tak, jak pierwotnie zrobił OP. Zamiar był jasny.
Mark Tolonen

43

Działa tak samo jak powyżej, ale nie obsługuje błędów:

s = open(filename, 'r').read()

21
Niezupełnie, twój pozostawia otwarty plik.
Ibz

3
Implementacja CPython zamyka plik, gdy liczba odwołań spadnie do zera, ale jest to szczegół implementacji, na którym nie należy polegać.
Mark Tolonen,

1
To obsługuje błędy; wyjątek zostanie wyrzucony jak zwykle. Nie powoduje to „pozostawienia pliku otwartego”, ale może spowodować opóźnienie zamknięcia pliku w zależności od implementacji GC. Może to być problem (blokowanie w systemie Windows i np. Limity FD w przypadku zapętlania wielu plików), ale to bardzo różni się od pozostawienia otwartego pliku (np. Wyciek pliku).
Glenn Maynard,

11
Jeśli twoim celem projektowym jest „jedna linia kodu”, wdychałeś za dużo Perla i musisz zaplanować trochę czasu na pranie mózgu.
Glenn Maynard,

6
Nie, to wcale nie jest mylące.
Glenn Maynard

37

Użyj pathlib .

Python 3.5 i nowsze:

from pathlib import Path
contents = Path(file_path).read_text()

W przypadku niższych wersji Pythona użyj pathlib2 :

$ pip install pathlib2

Następnie

from pathlib2 import Path
contents = Path(file_path).read_text()

Pisanie jest równie łatwe:

Path(file_path).write_text('my text')

18
contents = open(filename).read()

9
A kiedy zamykasz plik?
Ibz

1
@ionut bizau - Myślę, że kiedy zwrot open(...)jest zbierany jako śmieci. Niech ktoś mnie poprawi, jeśli się mylę.
detly

1
To jest najkrótsza droga. nie wiem, dlaczego nie ma głosów.
Pritesh Acharya

10

To nie jest Perl; nie chcesz na siłę dopasowywać wartości wielu wierszy kodu do jednej linii. Napisz funkcję, a następnie wywołanie funkcji pobiera jedną linię kodu.

def read_file(fn):
    """
    >>> import os
    >>> fn = "/tmp/testfile.%i" % os.getpid()
    >>> open(fn, "w+").write("testing")
    >>> read_file(fn)
    'testing'
    >>> os.unlink(fn)
    >>> read_file("/nonexistant")
    Traceback (most recent call last):
        ...
    IOError: [Errno 2] No such file or directory: '/nonexistant'
    """
    with open(fn) as f:
        return f.read()

if __name__ == "__main__":
    import doctest
    doctest.testmod()

5

Powolny, brzydki, specyficzny dla platformy ... ale jednolinijkowy ;-)

import subprocess

contents = subprocess.Popen('cat %s' % filename, shell = True, stdout = subprocess.PIPE).communicate()[0]

4
aaaaaaaaaaargh! (przekroczenie „a”, aby osiągnąć minimalny limit znaków)
Peter Gibson

6
Z pewnością pasuje do ducha pytania ... przewrotne użycie Pythona w celu upodobnienia go do Basha nie jest gorsze niż upodobnienie go do Rubiego lub Perla.
detly

3

Takie proste:

    f=open('myfile.txt')
    s=f.read()
    f.close()

I rób, co chcesz z treścią „s”


-1
contents = open(filename)

To daje generator, więc musisz gdzieś zapisać wartości, lub

contents = [line for line in open(filename)]

To sprawia, że ​​zapisanie na liście jawnie zamknij nie jest wtedy możliwe (przynajmniej przy mojej znajomości Pythona).


1
a z zawartością = '' .join (linia po linii w otwartym (nazwa pliku)) masz oryginalną zawartość pliku ...
eumiro

Użycie pliku jako iteratora nie zamyka pliku deterministycznie (jakwith robi). Nie może, ponieważ po zakończeniu iteracji nadal można wyszukać plik i ponownie rozpocząć czytanie, co nie zadziała, jeśli iteracja zamknie plik.
Glenn Maynard

@Glenn Ale jeśli używasz generatora do rozumienia list, jak w moim przykładzie, nie można go nawet zamknąć, ponieważ nie ma on nazwy.
Tony Veijalainen

„Brak możliwości zamknięcia” to nie to samo, co „nie trzeba go zamykać”.
Glenn Maynard,

Może tak, ale ty nie wiedziałbym, jak uzyskać dostęp do tego uchwytu pliku z wewnętrznego rozumienia listy. Czy powinno być może polecenie „zakończ wszystkie operacje we / wy, zamknij wszystkie otwarte pliki programu” w Pythonie? A może wystarczyłoby jawne gc dla obiektów plikowych? Uchwyt pliku jest poza zakresem, ponieważ rozumienie listy jest oddzielnym zakresem.
Tony Veijalainen
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.