Bagaimana cara membaca file baris demi baris ke dalam daftar?


2027

Bagaimana cara membaca setiap baris file dengan Python dan menyimpan setiap baris sebagai elemen dalam daftar?

Saya ingin membaca file baris demi baris dan menambahkan setiap baris ke akhir daftar.

Jawaban:


2174
with open(filename) as f:
    content = f.readlines()
# you may also want to remove whitespace characters like `\n` at the end of each line
content = [x.strip() for x in content] 

206
Jangan gunakan file.readlines()dalam for-loop, objek file itu sendiri sudah cukup:lines = [line.rstrip('\n') for line in file]
jfs

88
Jika Anda menggunakan Big Data menggunakan readlines()tidak sangat efisien karena dapat mengakibatkan MemoryError . Dalam hal ini lebih baik untuk beralih menggunakan file for line in f:dan bekerja dengan masing-masing linevariabel.
DarkCygnus

7
Saya memeriksa profil memori dengan berbagai cara yang diberikan dalam jawaban menggunakan prosedur yang disebutkan di sini . Penggunaan memori jauh lebih baik ketika setiap baris dibaca dari file dan diproses, seperti yang disarankan oleh @DevShark di sini . Memegang semua baris dalam objek koleksi bukan ide yang baik jika memori merupakan kendala atau file besar. Waktu eksekusi serupa di kedua pendekatan.
Tirtha R

6
Juga, .rstrip()akan bekerja sedikit lebih cepat jika Anda membuka spasi dari ujung garis.
Gringo Suave

Oneliner:with open(filename) as f: content = [i.strip() for i in f.readlines()]
Vishal Gupta

1002

Lihat Input dan Ouput :

with open('filename') as f:
    lines = f.readlines()

atau dengan stripping karakter baris baru:

with open('filename') as f:
    lines = [line.rstrip() for line in f]

12
Lebih baik, gunakan f.read().splitlines(), yang menghapus baris baru
Tandai

Apakah versi kedua, dengan for line in open(filename)aman? Yaitu, apakah file akan ditutup secara otomatis?
becko

2
Terbaik untuk membaca file satu baris sekaligus daripada membaca seluruh file ke memori sekaligus. Melakukannya tidak skala dengan baik dengan file input besar. Lihat jawaban di bawah ini oleh robert.
Brad Hein

1
lines = [x.rstrip('\n') for x in open('data\hsf.txt','r')]Jika saya menulis seperti ini, bagaimana saya bisa menutup file setelah membaca?
Ramisa Anjum Aditi

2
Ya, ke titik yang dibuat orang lain di sini, sementara itu bukan "praktik terbaik" untuk digunakan opentanpa manajer konteks (atau cara lain yang dijamin untuk menutupnya), ini sebenarnya bukan salah satu dari kasus tersebut - ketika objek tidak memiliki referensi lagi untuk itu akan menjadi sampah yang dikumpulkan dan file ditutup, yang seharusnya terjadi segera karena kesalahan atau tidak, ketika pemahaman daftar selesai diproses.
Aaron Hall

579

Ini lebih eksplisit daripada yang diperlukan, tetapi lakukan apa yang Anda inginkan.

with open("file.txt") as file_in:
    lines = []
    for line in file_in:
        lines.append(line)

18
Saya lebih suka jawaban ini karena tidak perlu memuat seluruh file ke dalam memori (dalam hal ini masih ditambahkan ke array , tetapi mungkin ada keadaan lain). Tentu saja untuk file besar pendekatan ini dapat mengurangi masalah.
JohannesB

1
Menambah array lambat. Saya tidak bisa memikirkan use case di mana ini adalah solusi terbaik.
Elias Strehle

@haccks apakah lebih baik karena tidak memuat seluruh file ke memori atau ada lebih banyak?
OrigamiEye

4
Catatan: Solusi ini tidak menghapus baris baru.
AMC

1
Solusi ini memuat seluruh file ke memori. Saya tidak tahu mengapa orang berpikir tidak.
andrebrait

274

Ini akan menghasilkan "array" baris dari file.

lines = tuple(open(filename, 'r'))

openmengembalikan file yang dapat diulangi. Ketika Anda mengulangi file, Anda mendapatkan garis dari file itu. tupledapat mengambil iterator dan instantiate instance tuple untuk Anda dari iterator yang Anda berikan. linesadalah tuple yang dibuat dari baris file.


31
@MarshallFarrier Cobalah lines = open(filename).read().split('\n')sebagai gantinya.
Noctis Skytower

16
apakah itu menutup file?
Vanuan

5
@Vanuan Karena tidak ada referensi yang tersisa ke file setelah baris dijalankan, destruktor harus secara otomatis menutup file.
Noctis Skytower

30
@NoctisSkytower Saya menemukan lines = open(filename).read().splitlines()sedikit lebih bersih, dan saya percaya itu juga menangani akhir baris DOS yang lebih baik.
jaynp

8
@ mklement0 Dengan asumsi file 1000 baris, a listmemakan sekitar 13,22% lebih banyak ruang daripada a tuple. Hasil datang dari from sys import getsizeof as g; i = [None] * 1000; round((g(list(i)) / g(tuple(i)) - 1) * 100, 2). Menciptakan tuplemembutuhkan waktu sekitar 4,17% lebih banyak waktu daripada membuat list(dengan standar deviasi 0,16%). Hasil datang dari menjalankan from timeit import timeit as t; round((t('tuple(i)', 'i = [None] * 1000') / t('list(i)', 'i = [None] * 1000') - 1) * 100, 2)30 kali. Solusi saya mendukung ruang lebih dari kecepatan ketika kebutuhan untuk berubah tidak diketahui.
Noctis Skytower

194

Jika Anda ingin yang \ndisertakan:

with open(fname) as f:
    content = f.readlines()

Jika Anda tidak ingin \ndisertakan:

with open(fname) as f:
    content = f.read().splitlines()

168

Menurut Metode File Objek Python , cara paling sederhana untuk mengubah file teks menjadi list:

with open('file.txt') as f:
    my_list = list(f)

Jika Anda hanya perlu mengulangi baris file teks, Anda dapat menggunakan:

with open('file.txt') as f:
    for line in f:
       ...

Jawaban lama:

Menggunakan withdan readlines():

with open('file.txt') as f:
    lines = f.readlines()

Jika Anda tidak peduli tentang penutupan file, one-liner ini berfungsi:

lines = open('file.txt').readlines()

Cara tradisional :

f = open('file.txt') # Open file on read mode
lines = f.read().split("\n") # Create a list containing all lines
f.close() # Close file

150

Anda dapat melakukan hal berikut, seperti yang disarankan:

with open('/your/path/file') as f:
    my_lines = f.readlines()

Perhatikan bahwa pendekatan ini memiliki 2 kelemahan:

1) Anda menyimpan semua baris dalam memori. Dalam kasus umum, ini adalah ide yang sangat buruk. File bisa sangat besar, dan Anda bisa kehabisan memori. Bahkan jika itu tidak besar, itu hanya membuang-buang memori.

2) Ini tidak memungkinkan pemrosesan setiap baris saat Anda membacanya. Jadi, jika Anda memproses baris Anda setelah ini, itu tidak efisien (membutuhkan dua lintasan daripada satu).

Pendekatan yang lebih baik untuk kasus umum adalah sebagai berikut:

with open('/your/path/file') as f:
    for line in f:
        process(line)

Di mana Anda mendefinisikan fungsi proses Anda dengan cara apa pun yang Anda inginkan. Sebagai contoh:

def process(line):
    if 'save the world' in line.lower():
         superman.save_the_world()

(Implementasi dari Superman kelas dibiarkan sebagai latihan untuk Anda).

Ini akan bekerja dengan baik untuk ukuran file apa pun dan Anda pergi melalui file Anda hanya dalam 1 pass. Ini biasanya bagaimana parser generik akan bekerja.


5
Ini persis apa yang saya butuhkan - dan terima kasih telah menjelaskan kerugiannya. Sebagai pemula di Python, itu luar biasa untuk memahami mengapa solusi adalah solusinya. Bersulang!
Ephexx

5
Pikirkan Corey sedikit lebih. Apakah Anda benar-benar ingin komputer Anda membaca setiap baris, tanpa pernah melakukan apa pun dengan baris ini? Tentunya Anda dapat menyadari bahwa Anda selalu perlu memprosesnya dengan satu atau lain cara.
DevShark

5
Anda selalu perlu melakukan sesuatu dengan garis. Ini bisa sesederhana mencetak garis, atau menghitungnya. Tidak ada gunanya meminta proses Anda membaca baris di memori, tetapi tidak melakukan apa-apa dengannya.
DevShark

2
Anda selalu perlu melakukan sesuatu dengan mereka. Saya pikir poin yang Anda coba buat adalah bahwa Anda mungkin ingin menerapkan fungsi pada semuanya sekaligus, daripada satu per satu. Memang itulah yang terkadang terjadi. Tetapi sangat tidak efisien dari sudut pandang memori untuk melakukannya, dan mencegah Anda membaca file jika jejaknya lebih besar dari Ram Anda. Itulah sebabnya biasanya parser generik beroperasi seperti yang saya gambarkan.
DevShark

2
@PierreOcinom itu benar. Karena file dibuka dalam mode hanya baca, Anda tidak dapat mengubah file asli dengan kode di atas. Untuk membuka file untuk membaca dan menulis, gunakanopen('file_path', 'r+')
DevShark

66

Data menjadi daftar

Anggap kita memiliki file teks dengan data kita seperti pada baris berikut,

Konten file teks:

line 1
line 2
line 3
  • Buka cmd di direktori yang sama (klik kanan mouse dan pilih cmd atau PowerShell)
  • Jalankan pythondan tulis dalam interpreter:

Skrip Python:

>>> with open("myfile.txt", encoding="utf-8") as file:
...     x = [l.rstrip("\n") for l in file]
>>> x
['line 1','line 2','line 3']

Menggunakan menambahkan:

x = []
with open("myfile.txt") as file:
    for l in file:
        x.append(l.strip())

Atau:

>>> x = open("myfile.txt").read().splitlines()
>>> x
['line 1', 'line 2', 'line 3']

Atau:

>>> x = open("myfile.txt").readlines()
>>> x
['linea 1\n', 'line 2\n', 'line 3\n']

Atau:

def print_output(lines_in_textfile):
    print("lines_in_textfile =", lines_in_textfile)

y = [x.rstrip() for x in open("001.txt")]
print_output(y)

with open('001.txt', 'r', encoding='utf-8') as file:
    file = file.read().splitlines()
    print_output(file)

with open('001.txt', 'r', encoding='utf-8') as file:
    file = [x.rstrip("\n") for x in file]
    print_output(file)

keluaran:

lines_in_textfile = ['line 1', 'line 2', 'line 3']
lines_in_textfile = ['line 1', 'line 2', 'line 3']
lines_in_textfile = ['line 1', 'line 2', 'line 3']

1
read().splitlines()disediakan untuk Anda oleh Python: itu sederhana readlines()(yang mungkin lebih cepat, karena kurang boros).
Eric O Lebigot

1
@ EricOLebigot dari contoh yang ditampilkan, sepertinya read().splitlines()dan readlines()tidak menghasilkan output yang sama. Apakah Anda yakin mereka setara?
craq

1
Jika Anda hanya menggunakan readlines, Anda perlu menggunakan metode strip untuk menyingkirkan \ n dalam teks, jadi saya mengubah contoh terakhir menggunakan daftar pemahaman untuk memiliki output yang sama di kedua kasus. Jadi, jika Anda menggunakan read (). Readlines () Anda akan memiliki item "bersih" dengan baris dan tanpa karakter baru, jika tidak, Anda harus melakukan apa yang Anda lihat dalam kode di atas.
Giovanni G. PY

1
Memang. Perhatikan bahwa dalam kode di atas semua yang strip()seharusnya rstrip("\n")atau spasi di sekitar baris dihapus. Juga, tidak ada gunanya melakukan readlines()dalam pemahaman daftar: hanya iterasi file lebih baik, karena tidak membuang waktu dan memori dengan membuat daftar perantara baris.
Eric O Lebigot

1
@EricOLebigot Selesai, terima kasih.
Giovanni G. PY

43

Untuk membaca file ke dalam daftar, Anda perlu melakukan tiga hal:

  • Buka file
  • Baca file tersebut
  • Simpan konten sebagai daftar

Untungnya Python membuatnya sangat mudah untuk melakukan hal-hal ini sehingga cara terpendek untuk membaca file ke dalam daftar adalah:

lst = list(open(filename))

Namun saya akan menambahkan beberapa penjelasan.

Membuka file

Saya berasumsi bahwa Anda ingin membuka file tertentu dan Anda tidak berurusan langsung dengan file-handle (atau file-like-handle). Fungsi yang paling umum digunakan untuk membuka file dalam Python adalah open, dibutuhkan satu argumen wajib dan dua opsional dalam Python 2.7:

  • Nama file
  • Mode
  • Buffering (Saya akan mengabaikan argumen ini dalam jawaban ini)

Nama file harus berupa string yang mewakili jalur ke file . Sebagai contoh:

open('afile')   # opens the file named afile in the current working directory
open('adir/afile')            # relative path (relative to the current working directory)
open('C:/users/aname/afile')  # absolute path (windows)
open('/usr/local/afile')      # absolute path (linux)

Perhatikan bahwa ekstensi file perlu ditentukan. Ini sangat penting bagi pengguna Windows karena ekstensi file seperti .txtatau .doc, dll. Disembunyikan secara default ketika dilihat di explorer.

Argumen kedua adalah mode, ini rsecara default yang berarti "hanya-baca". Itulah tepatnya yang Anda butuhkan dalam kasus Anda.

Tetapi jika Anda benar-benar ingin membuat file dan / atau menulis ke file Anda akan memerlukan argumen yang berbeda di sini. Ada jawaban yang sangat bagus jika Anda ingin ikhtisar .

Untuk membaca file, Anda dapat menghilangkan modeatau meneruskannya secara eksplisit:

open(filename)
open(filename, 'r')

Keduanya akan membuka file dalam mode read-only. Jika Anda ingin membaca dalam file biner pada Windows Anda perlu menggunakan mode rb:

open(filename, 'rb')

Pada platform lain, 'b'(mode biner) diabaikan.


Sekarang saya telah menunjukkan cara ke openfile, mari kita bicara tentang fakta bahwa Anda selalu membutuhkannya closelagi. Kalau tidak, ia akan menyimpan file-handle yang terbuka ke file sampai proses keluar (atau Python membuat file-handle).

Meskipun Anda dapat menggunakan:

f = open(filename)
# ... do stuff with f
f.close()

Itu akan gagal untuk menutup file ketika ada sesuatu di antara opendan closemelempar pengecualian. Anda bisa menghindarinya dengan menggunakan a trydan finally:

f = open(filename)
# nothing in between!
try:
    # do stuff with f
finally:
    f.close()

Namun Python menyediakan manajer konteks yang memiliki sintaks cantik (tapi untuk openitu hampir identik dengan trydan finallyatas):

with open(filename) as f:
    # do stuff with f
# The file is always closed after the with-scope ends.

Pendekatan terakhir adalah yang direkomendasikan untuk membuka file dengan Python!

Membaca file

Oke, Anda sudah membuka file, sekarang bagaimana cara membacanya?

The openmengembalikan fungsi fileobjek dan mendukung Piton protokol iterasi. Setiap iterasi akan memberi Anda garis:

with open(filename) as f:
    for line in f:
        print(line)

Ini akan mencetak setiap baris file. Perhatikan bahwa setiap baris akan berisi karakter baris baru \ndi bagian akhir (Anda mungkin ingin memeriksa apakah Python Anda dibangun dengan dukungan baris baru universal - jika tidak, Anda juga bisa \r\nmenggunakan Windows atau \rMac sebagai baris baru). Jika Anda tidak mau, Anda bisa menghapus karakter terakhir (atau dua karakter terakhir di Windows):

with open(filename) as f:
    for line in f:
        print(line[:-1])

Tapi baris terakhir tidak harus memiliki baris baru, jadi jangan gunakan itu. Orang dapat memeriksa apakah itu berakhir dengan baris baru tambahan dan jika demikian hapus:

with open(filename) as f:
    for line in f:
        if line.endswith('\n'):
            line = line[:-1]
        print(line)

Tapi Anda hanya bisa menghapus semua spasi putih (termasuk \nkarakter) dari akhir string , ini juga akan menghapus semua lainnya Trailing spasi putih sehingga Anda harus berhati-hati jika ini penting:

with open(filename) as f:
    for line in f:
        print(f.rstrip())

Namun jika garis berakhir dengan \r\n(Windows "baris baru") yang .rstrip()juga akan mengurus\r !

Simpan konten sebagai daftar

Sekarang setelah Anda tahu cara membuka file dan membacanya, saatnya untuk menyimpan konten dalam daftar. Opsi paling sederhana adalah menggunakan listfungsi:

with open(filename) as f:
    lst = list(f)

Jika Anda ingin menghapus baris baru, Anda bisa menggunakan pemahaman daftar sebagai gantinya:

with open(filename) as f:
    lst = [line.rstrip() for line in f]

Atau bahkan lebih sederhana: .readlines()Metode fileobjek secara default mengembalikan a listdari baris:

with open(filename) as f:
    lst = f.readlines()

Ini juga akan menyertakan karakter baris baru yang tertinggal, jika Anda tidak menginginkannya, saya akan merekomendasikan [line.rstrip() for line in f]pendekatan karena menghindari menyimpan dua daftar yang berisi semua baris dalam memori.

Ada opsi tambahan untuk mendapatkan output yang diinginkan, namun ini agak "suboptimal": readfile lengkap dalam sebuah string dan kemudian dibagi pada baris baru:

with open(filename) as f:
    lst = f.read().split('\n')

atau:

with open(filename) as f:
    lst = f.read().splitlines()

Ini menangani baris baru yang tertinggal secara otomatis karena splitkarakter tidak termasuk. Namun mereka tidak ideal karena Anda menyimpan file sebagai string dan sebagai daftar baris dalam memori!

Ringkasan

  • Gunakan with open(...) as fsaat membuka file karena Anda tidak perlu mengurus sendiri penutupan file dan menutup file bahkan jika beberapa pengecualian terjadi.
  • fileobjek mendukung protokol iterasi sehingga membaca file baris demi baris sesederhana for line in the_file_object:.
  • Selalu telusuri dokumentasi untuk fungsi / kelas yang tersedia. Sebagian besar waktu ada pasangan yang cocok untuk tugas atau setidaknya satu atau dua yang bagus. Pilihan yang jelas dalam kasus ini adalah readlines()tetapi jika Anda ingin memproses baris sebelum menyimpannya dalam daftar, saya akan merekomendasikan daftar-pemahaman sederhana.

Pendekatan terakhir adalah pendekatan yang disarankan untuk membuka file dengan Python! Mengapa ini terakhir? Bukankah sebagian besar orang hanya akan melirik beberapa baris pertama jawaban sebelum melanjutkan?
AMC

@ AMC Saya belum terlalu memikirkannya ketika saya menulis jawabannya. Apakah Anda pikir saya harus meletakkannya di bagian atas jawaban?
MSeifert

Mungkin yang terbaik, ya. Saya juga baru memperhatikan bahwa Anda menyebutkan Python 2, sehingga bisa diperbarui juga.
AMC

Ah pertanyaannya awalnya ditandai python-2.x. Masuk akal untuk memperbaruinya secara lebih umum. Saya akan melihat apakah saya akan membahasnya nanti. Terima kasih atas saran Anda. Sangat dihargai!
MSeifert

42

Cara Bersih dan Pythonic Membaca Garis-Garis File Menjadi Daftar


Pertama dan terutama, Anda harus fokus pada membuka file Anda dan membaca isinya dengan cara yang efisien dan pythonic. Ini adalah contoh dari cara yang secara pribadi TIDAK Saya sukai:

infile = open('my_file.txt', 'r')  # Open the file for reading.

data = infile.read()  # Read the contents of the file.

infile.close()  # Close the file since we're done using it.

Sebaliknya, saya lebih suka metode membuka file di bawah ini untuk membaca dan menulis karena sangat bersih, dan tidak memerlukan langkah tambahan untuk menutup file setelah Anda selesai menggunakannya. Dalam pernyataan di bawah ini, kami membuka file untuk dibaca, dan menugaskannya ke variabel 'infile.' Setelah kode dalam pernyataan ini selesai berjalan, file akan ditutup secara otomatis.

# Open the file for reading.
with open('my_file.txt', 'r') as infile:

    data = infile.read()  # Read the contents of the file into memory.

Sekarang kita perlu fokus untuk membawa data ini ke dalam Daftar Python karena mereka dapat diubah, efisien, dan fleksibel. Dalam kasus Anda, tujuan yang diinginkan adalah untuk membawa setiap baris file teks ke elemen yang terpisah. Untuk mencapai ini, kami akan menggunakan metode splitlines () sebagai berikut:

# Return a list of the lines, breaking at line boundaries.
my_list = data.splitlines()

Produk Akhir:

# Open the file for reading.
with open('my_file.txt', 'r') as infile:

    data = infile.read()  # Read the contents of the file into memory.

# Return a list of the lines, breaking at line boundaries.
my_list = data.splitlines()

Menguji Kode Kami:

  • Isi file teks:
     A fost odatĂŁ ca-n povesti,
     A fost ca niciodatĂŁ,
     Din rude mãri împãrãtesti,
     O prea frumoasĂŁ fatĂŁ.
  • Pernyataan cetak untuk tujuan pengujian:
    print my_list  # Print the list.

    # Print each line in the list.
    for line in my_list:
        print line

    # Print the fourth element in this list.
    print my_list[3]
  • Output (tampak berbeda karena karakter unicode):
     ['A fost odat\xc3\xa3 ca-n povesti,', 'A fost ca niciodat\xc3\xa3,',
     'Din rude m\xc3\xa3ri \xc3\xaemp\xc3\xa3r\xc3\xa3testi,', 'O prea
     frumoas\xc3\xa3 fat\xc3\xa3.']

     A fost odatĂŁ ca-n povesti, A fost ca niciodatĂŁ, Din rude mĂŁri
     împãrãtesti, O prea frumoasã fatã.

     O prea frumoasĂŁ fatĂŁ.

30

Diperkenalkan dalam Python 3.4, pathlibmemiliki metode yang sangat nyaman untuk membaca teks dari file, sebagai berikut:

from pathlib import Path
p = Path('my_text_file')
lines = p.read_text().splitlines()

( splitlinesPanggilan inilah yang mengubahnya dari string yang berisi seluruh isi file ke daftar baris dalam file).

pathlibmemiliki banyak kenyamanan praktis di dalamnya. read_textbagus dan ringkas, dan Anda tidak perlu khawatir tentang membuka dan menutup file. Jika semua yang perlu Anda lakukan dengan file tersebut adalah membacanya semuanya sekaligus, itu adalah pilihan yang baik.


29

Berikut ini satu opsi lagi dengan menggunakan daftar pemahaman pada file;

lines = [line.rstrip() for line in open('file.txt')]

Ini harus menjadi cara yang lebih efisien karena sebagian besar pekerjaan dilakukan di dalam juru bahasa Python.


10
rstrip()berpotensi menghapus semua spasi spasi, tidak hanya \n; gunakan .rstrip('\n').
mklement0

Ini juga tidak menjamin bahwa file akan ditutup setelah membaca di semua implementasi Python (walaupun dalam CPython, implementasi Python utama, itu akan menjadi).
Mark Amery

1
Ini harus menjadi cara yang lebih efisien karena sebagian besar pekerjaan dilakukan di dalam interpreter Python. Apa artinya?
AMC

28
f = open("your_file.txt",'r')
out = f.readlines() # will append in the list out

Sekarang variabel keluar adalah daftar (array) dari apa yang Anda inginkan. Anda bisa melakukan:

for line in out:
    print (line)

Atau:

for line in f:
    print (line)

Anda akan mendapatkan hasil yang sama.


27

Baca dan tulis file teks dengan Python 2 dan Python 3; ini bekerja dengan Unicode

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Define data
lines = ['     A first string  ',
         'A Unicode sample: €',
         'German: äöüß']

# Write text file
with open('file.txt', 'w') as fp:
    fp.write('\n'.join(lines))

# Read text file
with open('file.txt', 'r') as fp:
    read_lines = fp.readlines()
    read_lines = [line.rstrip('\n') for line in read_lines]

print(lines == read_lines)

Hal-hal yang perlu diperhatikan:

  • withadalah yang disebut manajer konteks . Itu memastikan bahwa file yang dibuka ditutup lagi.
  • Semua solusi di sini yang hanya membuat .strip()atau .rstrip()akan gagal mereproduksi lineskarena mereka juga menghilangkan ruang putih.

Ujung file umum

.txt

Penulisan / pembacaan file lebih lanjut

Untuk aplikasi Anda, berikut ini mungkin penting:

  • Dukungan oleh bahasa pemrograman lain
  • Kinerja membaca / menulis
  • Kekompakan (ukuran file)

Lihat juga: Perbandingan format serialisasi data

Jika Anda lebih suka mencari cara untuk membuat file konfigurasi, Anda mungkin ingin membaca artikel pendek saya File konfigurasi dalam Python .


26

Pilihan lain adalah numpy.genfromtxt, misalnya:

import numpy as np
data = np.genfromtxt("yourfile.dat",delimiter="\n")

Ini akan membuat dataarray NumPy dengan sebanyak mungkin baris dalam file Anda.


25

Jika Anda ingin membaca file dari baris perintah atau dari stdin, Anda juga dapat menggunakan fileinputmodul:

# reader.py
import fileinput

content = []
for line in fileinput.input():
    content.append(line.strip())

fileinput.close()

Lewati file seperti itu:

$ python reader.py textfile.txt 

Baca lebih lanjut di sini: http://docs.python.org/2/library/fileinput.html


20

Cara paling sederhana untuk melakukannya

Cara sederhana adalah dengan:

  1. Baca seluruh file sebagai string
  2. Pisahkan garis demi garis string

Dalam satu baris, itu akan memberi:

lines = open('C:/path/file.txt').read().splitlines()

Namun, ini cara yang tidak efisien karena ini akan menyimpan 2 versi konten dalam memori (mungkin bukan masalah besar untuk file kecil, tapi tetap saja). [Terima kasih, Mark Amery].

Ada 2 cara yang lebih mudah:

  1. Menggunakan file sebagai iterator
lines = list(open('C:/path/file.txt'))
# ... or if you want to have a list without EOL characters
lines = [l.rstrip() for l in open('C:/path/file.txt')]
  1. Jika Anda menggunakan Python 3.4 atau lebih, gunakan lebih baik pathlibuntuk membuat jalur untuk file Anda yang bisa Anda gunakan untuk operasi lain dalam program Anda:
from pathlib import Path
file_path = Path("C:/path/file.txt") 
lines = file_path.read_text().split_lines()
# ... or ... 
lines = [l.rstrip() for l in file_path.open()]

Ini pendekatan yang buruk. Untuk satu hal, menelepon .read().splitlines()sama sekali tidak "sederhana" dari sekadar menelepon .readlines(). Untuk yang lain, itu tidak efisien dalam memori; Anda tidak perlu menyimpan dua versi konten file (string tunggal yang dikembalikan oleh .read(), dan daftar string yang dikembalikan oleh splitlines()) dalam memori sekaligus.
Mark Amery

@MarkAmery Benar. Terima kasih telah menyoroti ini. Saya telah memperbarui jawaban saya.
Jean-Francois T.

14

Cukup gunakan fungsi splitlines (). Berikut ini sebuah contoh.

inp = "file.txt"
data = open(inp)
dat = data.read()
lst = dat.splitlines()
print lst
# print(lst) # for python 3

Dalam output Anda akan memiliki daftar baris.


Memori-tidak efisien dibandingkan menggunakan .readlines(). Ini menempatkan dua salinan isi file dalam memori sekaligus (satu sebagai string besar, satu sebagai daftar baris).
Mark Amery

11

Jika Anda ingin dihadapkan dengan file yang sangat besar / besar dan ingin membaca lebih cepat (bayangkan Anda berada dalam kompetisi pengkodean Topcoder / Hackerrank), Anda mungkin membaca sepotong baris yang jauh lebih besar ke buffer memori pada satu waktu, daripada iterate baris demi baris di tingkat file.

buffersize = 2**16
with open(path) as f: 
    while True:
        lines_buffer = f.readlines(buffersize)
        if not lines_buffer:
            break
        for line in lines_buffer:
            process(line)

apa yang dilakukan proses (garis)? Saya mendapatkan kesalahan karena tidak ada variabel yang ditentukan. Saya kira sesuatu perlu diimpor dan saya mencoba mengimpor multiprocessing. Proses, tapi bukan itu yang saya kira. Bisakah Anda jelaskan? Terima kasih
Newskooler

1
process(line)adalah fungsi yang perlu Anda terapkan untuk memproses data. misalnya, alih-alih baris itu, jika Anda gunakan print(line), itu akan mencetak setiap baris dari lines_buffer.
Khanal

f.readlines (buffersize) mengembalikan buffer yang tidak dapat diubah. jika Anda ingin langsung membaca buffer Anda, Anda perlu menggunakan fungsi readinto (). Saya akan jauh lebih cepat.
David Dehghan

7

Cara termudah untuk melakukannya dengan beberapa manfaat tambahan adalah:

lines = list(open('filename'))

atau

lines = tuple(open('filename'))

atau

lines = set(open('filename'))

Dalam hal ini set, kita harus diingat bahwa kita tidak memiliki urutan garis yang dipertahankan dan menyingkirkan garis yang digandakan.

Di bawah ini saya menambahkan suplemen penting dari @MarkAmery :

Karena Anda tidak memanggil .closeobjek file atau menggunakan withpernyataan, dalam beberapa implementasi Python file mungkin tidak akan ditutup setelah membaca dan proses Anda akan bocor menangani file yang terbuka .

Dalam CPython ( implementasi Python normal yang digunakan kebanyakan orang), ini bukan masalah karena objek file akan segera mengumpulkan sampah dan ini akan menutup file, tetapi meskipun demikian umumnya dianggap praktik terbaik untuk melakukan sesuatu seperti :

with open('filename') as f: lines = list(f) 

untuk memastikan bahwa file akan ditutup terlepas dari implementasi Python apa yang Anda gunakan.


1
Karena Anda tidak memanggil .closeobjek file atau menggunakan withpernyataan, dalam beberapa implementasi Python file mungkin tidak akan ditutup setelah membaca dan proses Anda akan bocor menangani file yang terbuka. Dalam CPython (implementasi Python normal yang kebanyakan orang gunakan), ini bukan masalah karena objek file akan segera mengumpulkan sampah dan ini akan menutup file, tetapi tetap dianggap praktik terbaik untuk melakukan sesuatu seperti with open('filename') as f: lines = list(f)memastikan bahwa file akan ditutup terlepas dari apa implementasi Python yang Anda gunakan.
Mark Amery

Terima kasih atas komentar Anda yang luar biasa @MarkAmery! Saya sangat menghargai itu.
simhumileco

1
@simhumileco Mengapa solusi terbaik (benar) bertahan?
AMC

@ AMC karena pertama, saya ingin menunjukkan cara paling sederhana dan untuk konsistensi penalaran.
simhumileco

Selain itu, saya harap jawaban saya dibuat sehingga singkat dan mudah dibaca.
simhumileco

4

Gunakan ini:

import pandas as pd
data = pd.read_csv(filename) # You can also add parameters such as header, sep, etc.
array = data.values

dataadalah tipe dataframe, dan menggunakan nilai untuk mendapatkan ndarray. Anda juga bisa mendapatkan daftar dengan menggunakan array.tolist().


pandas.read_csv()adalah untuk membaca data CSV , bagaimana cara tepat di sini?
AMC

4

Garis Besar dan Ringkasan

Dengan filename, menangani file dari Path(filename)objek, atau langsung dengan open(filename) as f, lakukan salah satu hal berikut ini:

  • list(fileinput.input(filename))
  • menggunakan with path.open() as f, hubungif.readlines()
  • list(f)
  • path.read_text().splitlines()
  • path.read_text().splitlines(keepends=True)
  • beralih di atas fileinput.inputatau fdan list.appendsetiap baris satu per satu
  • lolos fke list.extendmetode terikat
  • gunakan fdalam pemahaman daftar

Saya jelaskan use-case untuk masing-masing di bawah ini.

Dengan Python, bagaimana cara membaca file baris demi baris?

Ini adalah pertanyaan yang sangat bagus. Pertama, mari kita buat beberapa data sampel:

from pathlib import Path
Path('filename').write_text('foo\nbar\nbaz')

File objek adalah iterator yang malas, jadi lakukan iterate saja.

filename = 'filename'
with open(filename) as f:
    for line in f:
        line # do something with the line

Atau, jika Anda memiliki banyak file, gunakan fileinput.input, iterator malas lainnya. Hanya dengan satu file:

import fileinput

for line in fileinput.input(filename): 
    line # process the line

atau untuk banyak file, berikan daftar nama file:

for line in fileinput.input([filename]*2): 
    line # process the line

Sekali lagi, fdan di fileinput.inputatas keduanya adalah / kembali iterators malas. Anda hanya dapat menggunakan iterator satu kali, jadi untuk memberikan kode fungsional sambil menghindari verbositas, saya akan menggunakan sedikit lebih singkat di fileinput.input(filename)mana apropos dari sini.

Dengan Python, bagaimana cara membaca file baris demi baris ke dalam daftar?

Ah, tetapi Anda menginginkannya dalam daftar karena suatu alasan? Saya akan menghindari itu jika memungkinkan. Tetapi jika Anda bersikeras ... sampaikan saja fileinput.input(filename)kepada list:

list(fileinput.input(filename))

Jawaban langsung lainnya adalah menelepon f.readlines, yang mengembalikan konten file (hingga hintsejumlah karakter opsional , sehingga Anda dapat memecahnya menjadi beberapa daftar dengan cara itu).

Anda bisa mendapatkan objek file ini dengan dua cara. Salah satu caranya adalah meneruskan nama file ke openbuiltin:

filename = 'filename'

with open(filename) as f:
    f.readlines()

atau menggunakan objek Path baru dari pathlibmodul (yang telah saya sukai, dan akan digunakan mulai sekarang):

from pathlib import Path

path = Path(filename)

with path.open() as f:
    f.readlines()

list juga akan mengkonsumsi file iterator dan mengembalikan daftar - metode yang cukup langsung:

with path.open() as f:
    list(f)

Jika Anda tidak keberatan membaca seluruh teks ke dalam memori sebagai string tunggal sebelum membaginya, Anda dapat melakukan ini sebagai satu-baris dengan Pathobjek dan splitlines()metode string. Secara default, splitlineshapus baris baru:

path.read_text().splitlines()

Jika Anda ingin mempertahankan baris baru, sampaikan keepends=True:

path.read_text().splitlines(keepends=True)

Saya ingin membaca file baris demi baris dan menambahkan setiap baris ke akhir daftar.

Sekarang ini agak konyol untuk bertanya, mengingat bahwa kami telah menunjukkan hasil akhirnya dengan mudah dengan beberapa metode. Tetapi Anda mungkin perlu memfilter atau mengoperasikan saluran saat Anda membuat daftar, jadi mari kita selesaikan permintaan ini.

Menggunakan list.appendakan memungkinkan Anda untuk memfilter atau beroperasi pada setiap baris sebelum Anda menambahkannya:

line_list = []
for line in fileinput.input(filename):
    line_list.append(line)

line_list

Penggunaan list.extendakan sedikit lebih langsung, dan mungkin berguna jika Anda memiliki daftar yang sudah ada sebelumnya:

line_list = []
line_list.extend(fileinput.input(filename))
line_list

Atau lebih secara idiomatis, kita bisa menggunakan pemahaman daftar, dan memetakan dan memfilter di dalamnya jika diinginkan:

[line for line in fileinput.input(filename)]

Atau bahkan lebih langsung, untuk menutup lingkaran, cukup kirimkan ke daftar untuk membuat daftar baru secara langsung tanpa beroperasi pada garis:

list(fileinput.input(filename))

Kesimpulan

Anda telah melihat banyak cara untuk mendapatkan baris dari file ke dalam daftar, tetapi saya sarankan Anda menghindari mematerialisasi data dalam jumlah besar ke dalam daftar dan alih-alih menggunakan iterasi malas Python untuk memproses data jika memungkinkan.

Yaitu, lebih suka fileinput.inputatau with path.open() as f.


4

Dalam hal ada juga baris kosong di dokumen saya suka membaca konten dan meneruskannya filteruntuk mencegah elemen string kosong

with open(myFile, "r") as f:
    excludeFileContent = list(filter(None, f.read().splitlines()))

1
Ini unpythonic, hati-hati.
AMC

3

Anda juga bisa menggunakan perintah loadtxt di NumPy. Ini memeriksa kondisi yang lebih sedikit daripada genfromtxt, jadi mungkin lebih cepat.

import numpy
data = numpy.loadtxt(filename, delimiter="\n")

2

Saya suka menggunakan yang berikut ini. Segera baca dialognya.

contents = []
for line in open(filepath, 'r').readlines():
    contents.append(line.strip())

Atau menggunakan pemahaman daftar:

contents = [line.strip() for line in open(filepath, 'r').readlines()]

2
Tidak perlu readlines(), yang bahkan menimbulkan hukuman memori. Anda cukup menghapusnya, karena iterasi file (teks) memberikan setiap baris pada gilirannya.
Eric O Lebigot

2
Anda harus menggunakan withpernyataan untuk membuka (dan secara implisit menutup) file tersebut.
Aran-Fey

2

Saya akan mencoba salah satu metode yang disebutkan di bawah ini. Contoh file yang saya gunakan memiliki nama dummy.txt. Anda dapat menemukan file di sini . Saya kira, file tersebut berada di direktori yang sama dengan kode (Anda dapat mengubah fpathuntuk memasukkan nama file dan jalur folder yang tepat.)

Dalam kedua contoh yang disebutkan di bawah ini, daftar yang Anda inginkan diberikan oleh lst.

1.> Metode pertama :

fpath = 'dummy.txt'
with open(fpath, "r") as f: lst = [line.rstrip('\n \t') for line in f]

print lst
>>>['THIS IS LINE1.', 'THIS IS LINE2.', 'THIS IS LINE3.', 'THIS IS LINE4.']

2.> Pada metode kedua , seseorang dapat menggunakan modul csv.reader dari Python Standard Library :

import csv
fpath = 'dummy.txt'
with open(fpath) as csv_file:
    csv_reader = csv.reader(csv_file, delimiter='   ')
    lst = [row[0] for row in csv_reader] 

print lst
>>>['THIS IS LINE1.', 'THIS IS LINE2.', 'THIS IS LINE3.', 'THIS IS LINE4.']

Anda dapat menggunakan salah satu dari dua metode ini. Waktu yang dibutuhkan untuk pembuatan lsthampir sama dalam dua metode.


1
Apa keuntungan dari pendekatan kedua? Mengapa meminta perpustakaan tambahan, yang menambahkan dalam kasus tepi (pembatas, dan kutipan)?
Charlie Harding

Untuk apa delimiter=' 'argumennya?
AMC

2

Berikut adalah kelas pustaka pembantu Python (3) yang saya gunakan untuk menyederhanakan file I / O:

import os

# handle files using a callback method, prevents repetition
def _FileIO__file_handler(file_path, mode, callback = lambda f: None):
  f = open(file_path, mode)
  try:
    return callback(f)
  except Exception as e:
    raise IOError("Failed to %s file" % ["write to", "read from"][mode.lower() in "r rb r+".split(" ")])
  finally:
    f.close()


class FileIO:
  # return the contents of a file
  def read(file_path, mode = "r"):
    return __file_handler(file_path, mode, lambda rf: rf.read())

  # get the lines of a file
  def lines(file_path, mode = "r", filter_fn = lambda line: len(line) > 0):
    return [line for line in FileIO.read(file_path, mode).strip().split("\n") if filter_fn(line)]

  # create or update a file (NOTE: can also be used to replace a file's original content)
  def write(file_path, new_content, mode = "w"):
    return __file_handler(file_path, mode, lambda wf: wf.write(new_content))

  # delete a file (if it exists)
  def delete(file_path):
    return os.remove() if os.path.isfile(file_path) else None

Anda kemudian akan menggunakan FileIO.linesfungsinya, seperti ini:

file_ext_lines = FileIO.lines("./path/to/file.ext"):
for i, line in enumerate(file_ext_lines):
  print("Line {}: {}".format(i + 1, line))

Ingat bahwa parameter mode( "r"secara default) dan filter_fn(memeriksa jalur kosong secara default) adalah opsional.

Anda bahkan dapat menghapus read, writedan deletemetode dan hanya meninggalkan FileIO.lines, atau bahkan mengubahnya menjadi metode terpisah yang disebut read_lines.


Apakah lines = FileIO.lines(path)benar-benar cukup sederhana daripada with open(path) as f: lines = f.readlines()membenarkan keberadaan penolong ini? Anda menyimpan, misalnya, 17 karakter per panggilan. (Dan sebagian besar waktu, untuk alasan kinerja dan memori, Anda ingin melompati objek file secara langsung alih-alih membaca barisnya menjadi daftar, sehingga Anda bahkan tidak ingin sering menggunakan ini!) Saya sering penggemar membuat sedikit fungsi utilitas, tetapi yang ini terasa bagi saya seperti itu hanya perlu menciptakan cara baru untuk menulis sesuatu yang sudah pendek dan mudah dengan perpustakaan standar memberi kita.
Mark Amery

Selain apa yang dikatakan @MarkAmery, mengapa menggunakan kelas untuk ini?
AMC

1

Versi baris perintah

#!/bin/python3
import os
import sys
abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
filename = dname + sys.argv[1]
arr = open(filename).read().split("\n") 
print(arr)

Jalankan dengan:

python3 somefile.py input_file_name.txt
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.