Bagaimana cara membaca file besar - baris demi baris?

536

Saya ingin mengulangi setiap baris seluruh file. Salah satu cara untuk melakukan ini adalah dengan membaca seluruh file, menyimpannya ke daftar, kemudian melewati batas yang diinginkan. Metode ini menggunakan banyak memori, jadi saya mencari alternatif.

Kode saya sejauh ini:

for each_line in fileinput.input(input_file):
    do_something(each_line)

    for each_line_again in fileinput.input(input_file):
        do_something(each_line_again)

Mengeksekusi kode ini memberikan pesan kesalahan: device active.

Ada saran?

Tujuannya adalah untuk menghitung kesamaan string pasangan-bijaksana, yang berarti untuk setiap baris dalam file, saya ingin menghitung jarak Levenshtein dengan setiap baris lainnya.

384X21
sumber
4
Mengapa Anda perlu membaca seluruh file lagi untuk setiap baris? Mungkin jika Anda memberi tahu apa yang ingin Anda capai, seseorang mungkin dapat menyarankan pendekatan yang lebih baik.
JJJ

Jawaban:

1269

Cara Pythonic yang benar dan sepenuhnya membaca file adalah sebagai berikut:

with open(...) as f:
    for line in f:
        # Do something with 'line'

The withpernyataan menangani pembukaan dan penutupan file, termasuk jika eksepsi dimunculkan di blok batin. The for line in fmemperlakukan file objek fsebagai iterable, yang secara otomatis menggunakan buffered I / O dan manajemen memori sehingga Anda tidak perlu khawatir tentang file besar.

Seharusnya ada satu - dan lebih disukai hanya satu - cara yang jelas untuk melakukannya.

Katriel
sumber
14
ya, ini adalah versi terbaik dengan python 2.6 dan di atasnya
Simon Bergot
3
Saya pribadi lebih suka generator & coroutine untuk berurusan dengan jalur pipa data.
jldupont
4
apa yang akan menjadi strategi terbaik jika file adalah file teks besar tetapi dengan satu baris dan idenya adalah untuk memproses kata-kata?
mfcabrera
4
Bisakah seseorang menjelaskan bagaimana cara for line in f:kerjanya? Maksud saya, bagaimana pengulangan objek file bisa dilakukan?
pukul
11
Jika Anda beralih pada suatu objek, Python mencari dalam daftar metode objek yang disebut khusus __iter__, yang memberitahukan apa yang harus dilakukan. Objek file mendefinisikan metode khusus ini untuk mengembalikan iterator melewati garis. (Secara kasar.)
Katriel
130

Dua cara efisien memori dalam urutan peringkat (pertama adalah yang terbaik) -

  1. penggunaan with- didukung dari python 2.5 dan di atasnya
  2. gunakan yieldjika Anda benar-benar ingin memiliki kontrol atas berapa banyak yang harus dibaca

1. penggunaan with

withadalah cara pythonic yang bagus dan efisien untuk membaca file besar. Keuntungan - 1) objek file secara otomatis ditutup setelah keluar dari withblok eksekusi. 2) penanganan eksepsi di dalam withblok. 3) memori forloop berulang melalui fobjek file baris demi baris. secara internal memang buffered IO (untuk dioptimalkan pada operasi IO yang mahal) dan manajemen memori.

with open("x.txt") as f:
    for line in f:
        do something with data

2. penggunaan yield

Kadang-kadang orang mungkin ingin kontrol yang lebih baik atas berapa banyak untuk dibaca di setiap iterasi. Dalam hal ini gunakan iter & hasilkan . Catatan dengan metode ini, seseorang secara eksplisit perlu menutup file di akhir.

def readInChunks(fileObj, chunkSize=2048):
    """
    Lazy function to read a file piece by piece.
    Default chunk size: 2kB.
    """
    while True:
        data = fileObj.read(chunkSize)
        if not data:
            break
        yield data

f = open('bigFile')
for chuck in readInChunks(f):
    do_something(chunk)
f.close()

Perangkap dan demi kelengkapan - metode di bawah ini tidak sebagus atau seanggun untuk membaca file besar tapi baca untuk mendapatkan pemahaman bulat.

Dengan Python, cara paling umum untuk membaca baris dari file adalah dengan melakukan hal berikut:

for line in open('myfile','r').readlines():
    do_something(line)

Ketika ini dilakukan, bagaimanapun, readlines()fungsi (sama berlaku untuk read()fungsi) memuat seluruh file ke dalam memori, kemudian beralih di atasnya. Pendekatan yang sedikit lebih baik (dua metode pertama adalah yang terbaik) untuk file besar adalah dengan menggunakan fileinputmodul, sebagai berikut:

import fileinput

for line in fileinput.input(['myfile']):
    do_something(line)

yang fileinput.input()panggilan membaca garis berurutan, tetapi tidak menjaga mereka dalam memori setelah mereka telah membaca atau bahkan hanya jadi ini, karena filedi python adalah iterable.

Referensi

  1. Python dengan pernyataan
Srikar Appalaraju
sumber
9
-1 Ini pada dasarnya tidak pernah merupakan ide yang baik untuk dilakukan for line in open(...).readlines(): <do stuff>. Mengapa kamu akan?! Anda baru saja kehilangan semua manfaat dari Ierator buffered pintar Python yang tidak bermanfaat.
Katriel
5
@Rikar: ada waktu dan tempat untuk memberikan semua solusi yang mungkin untuk suatu masalah; mengajar pemula cara melakukan input file bukan. Memiliki jawaban yang benar terkubur di bagian bawah posting panjang yang penuh dengan jawaban yang salah tidak menghasilkan pengajaran yang baik.
Katriel
6
@Rikar: Anda dapat membuat posting Anda lebih baik secara signifikan dengan menempatkan cara yang benar di atas, kemudian menyebutkan readlinesdan menjelaskan mengapa itu bukan hal yang baik untuk dilakukan (karena membaca file ke dalam memori), kemudian menjelaskan apa yang dilakukan fileinputmodul dan mengapa Anda mungkin ingin menggunakannya di atas metode lain, kemudian menjelaskan bagaimana memotong file membuat IO lebih baik dan memberikan contoh fungsi chunking (tetapi menyebutkan bahwa Python sudah melakukan ini untuk Anda sehingga Anda tidak perlu). Tetapi hanya memberikan lima cara untuk memecahkan masalah sederhana, empat di antaranya salah dalam kasus ini, tidak baik.
Katriel
2
Apa pun yang Anda tambahkan demi kelengkapan, tambahkan yang terakhir, bukan yang pertama. Pertama tunjukkan cara yang tepat.
m000
6
@katrielalex mengunjungi kembali jawaban saya & menemukan bahwa itu menjamin restrukturisasi. Saya bisa melihat bagaimana jawaban sebelumnya dapat menyebabkan kebingungan. Semoga ini akan menjelaskan bagi pengguna masa depan.
Srikar Appalaraju
37

Untuk menghapus baris baru:

with open(file_path, 'rU') as f:
    for line_terminated in f:
        line = line_terminated.rstrip('\n')
        ...

Dengan dukungan baris baru yang universal semua baris file teks akan tampak diakhiri dengan '\n', apa pun terminator dalam file, '\r', '\n', atau '\r\n'.

EDIT - Untuk menentukan dukungan baris baru universal:

  • Python 2 di Unix - open(file_path, mode='rU')- diperlukan [terima kasih @Dave ]
  • Python 2 di Windows - open(file_path, mode='rU')- opsional
  • Python 3 - open(file_path, newline=None)- opsional

The newlineParameter hanya didukung dengan Python 3 dan default untuk None. The modeparameter default untuk 'r'semua kasus. The Usudah ditinggalkan di Python 3. Dalam Python 2 pada Windows mekanisme lain muncul untuk menerjemahkan \r\nke \n.

Docs:

Untuk melestarikan terminator jalur asli:

with open(file_path, 'rb') as f:
    with line_native_terminated in f:
        ...

Mode biner masih dapat mem-parsing file menjadi beberapa baris in. Setiap baris akan memiliki terminator apa pun yang ada di file.

Terima kasih atas jawaban @katrielalex , Python terbuka () doc, dan iPython percobaan.

Bob Stein
sumber
1
Pada Python 2.7 saya harus open(file_path, 'rU')mengaktifkan baris baru universal.
Dave
17

ini adalah cara yang mungkin untuk membaca file dengan python:

f = open(input_file)
for line in f:
    do_stuff(line)
f.close()

itu tidak mengalokasikan daftar lengkap. Iterates melewati garis.

Simon Bergot
sumber
2
Sementara ini berhasil, itu jelas bukan cara kanonik. Cara kanonik adalah dengan menggunakan pembungkus konteks, seperti with open(input_file) as f:. Ini menghemat Anda f.close()dan memastikan Anda tidak sengaja lupa untuk menutupnya. Mencegah kebocoran memori dan semuanya, cukup penting saat membaca file.
Mast
1
Seperti yang dikatakan @Mast, itu bukan cara kanonik, jadi downvote untuk itu.
azuax
12

Beberapa konteks di depan tentang dari mana saya berasal. Cuplikan kode ada di akhir.

Ketika saya bisa, saya lebih suka menggunakan alat open source seperti H2O untuk membaca file CSV paralel kinerja tinggi, tetapi alat ini terbatas dalam rangkaian fitur. Saya akhirnya menulis banyak kode untuk membuat jalur data sains sebelum menyuapi cluster H2O untuk pembelajaran yang diawasi dengan baik.

Saya telah membaca file seperti dataset HIGGS 8GB dari repo UCI dan bahkan file CSV 40GB untuk tujuan ilmu data secara signifikan lebih cepat dengan menambahkan banyak paralelisme dengan objek kumpulan pustaka multiprocessing dan fungsi peta. Sebagai contoh pengelompokan dengan pencarian tetangga terdekat dan juga algoritma pengelompokan DBSCAN dan Markov memerlukan beberapa kemahiran pemrograman paralel untuk mem-bypass beberapa masalah memori dan waktu jam dinding yang sangat menantang.

Saya biasanya suka memecah file baris-bijaksana menjadi beberapa bagian menggunakan alat gnu pertama dan kemudian glob-filemask mereka semua untuk menemukan dan membacanya secara paralel dalam program python. Saya menggunakan sesuatu seperti 1000+ file parsial secara umum. Melakukan trik-trik ini sangat membantu dengan kecepatan pemrosesan dan batas memori.

Panda dataframe.read_csv adalah single threaded sehingga Anda dapat melakukan trik ini untuk membuat panda lebih cepat dengan menjalankan peta () untuk eksekusi paralel. Anda dapat menggunakan htop untuk melihat bahwa dengan panda lama berurutan, dataframe.read_csv, 100% cpu hanya pada satu inti adalah hambatan aktual dalam pd.read_csv, bukan disk sama sekali.

Saya harus menambahkan saya menggunakan SSD pada bus kartu video cepat, bukan HD berputar pada SATA6 bus, ditambah 16 core CPU.

Juga, teknik lain yang saya temukan berfungsi dengan baik dalam beberapa aplikasi adalah file CSV paralel membaca semua dalam satu file raksasa, mulai setiap pekerja dengan offset berbeda ke dalam file, daripada memisahkan satu file besar menjadi banyak file bagian. Gunakan file python mencari () dan memberi tahu () pada setiap pekerja paralel untuk membaca file teks besar dalam strip, pada byte berbeda mengimbangi lokasi mulai byte dan akhir byte dalam file besar, semua pada saat yang bersamaan bersamaan. Anda dapat melakukan pencarian regex pada byte, dan mengembalikan jumlah umpan baris. Ini adalah jumlah parsial. Akhirnya jumlahkan jumlah parsial untuk mendapatkan jumlah global ketika fungsi peta kembali setelah pekerja selesai.

Berikut ini adalah beberapa contoh benchmark menggunakan trik byte offset paralel:

Saya menggunakan 2 file: HIGGS.csv adalah 8 GB. Itu dari repositori pembelajaran mesin UCI. all_bin .csv adalah 40,4 GB dan dari proyek saya saat ini. Saya menggunakan 2 program: Program GNU wc yang datang dengan Linux, dan program python fastread.py murni yang saya kembangkan.

HP-Z820:/mnt/fastssd/fast_file_reader$ ls -l /mnt/fastssd/nzv/HIGGS.csv
-rw-rw-r-- 1 8035497980 Jan 24 16:00 /mnt/fastssd/nzv/HIGGS.csv

HP-Z820:/mnt/fastssd$ ls -l all_bin.csv
-rw-rw-r-- 1 40412077758 Feb  2 09:00 all_bin.csv

ga@ga-HP-Z820:/mnt/fastssd$ time python fastread.py --fileName="all_bin.csv" --numProcesses=32 --balanceFactor=2
2367496

real    0m8.920s
user    1m30.056s
sys 2m38.744s

In [1]: 40412077758. / 8.92
Out[1]: 4530501990.807175

Itu beberapa 4,5 GB / s, atau 45 Gb / s, file kecepatan menghirup. Itu bukan hard disk yang berputar, temanku. Itu sebenarnya Samsung Pro 950 SSD.

Di bawah ini adalah patokan kecepatan untuk file yang sama yang sedang dihitung baris oleh gnu wc, program yang dikompilasi C murni.

Apa yang keren adalah Anda dapat melihat program python murni saya pada dasarnya cocok dengan kecepatan program C yang dikompilasi gnu wc dalam kasus ini. Python ditafsirkan tetapi C dikompilasi, jadi ini adalah fitur kecepatan yang cukup menarik, saya pikir Anda akan setuju. Tentu saja, wc benar-benar perlu diubah ke program paralel, dan kemudian itu akan benar-benar mengalahkan kaus kaki dari program python saya. Tapi seperti yang ada sekarang, gnu wc hanyalah program berurutan. Anda melakukan apa yang Anda bisa, dan python dapat melakukan paralel hari ini. Kompilasi Cython mungkin dapat membantu saya (untuk beberapa waktu lain). Juga file yang dipetakan memori belum dieksplorasi.

HP-Z820:/mnt/fastssd$ time wc -l all_bin.csv
2367496 all_bin.csv

real    0m8.807s
user    0m1.168s
sys 0m7.636s


HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=16 --balanceFactor=2
11000000

real    0m2.257s
user    0m12.088s
sys 0m20.512s

HP-Z820:/mnt/fastssd/fast_file_reader$ time wc -l HIGGS.csv
11000000 HIGGS.csv

real    0m1.820s
user    0m0.364s
sys 0m1.456s

Kesimpulan: Kecepatannya baik untuk program python murni dibandingkan dengan program C. Namun, itu tidak cukup baik untuk menggunakan program python murni di atas program C, setidaknya untuk tujuan menghitung linec. Secara umum teknik ini dapat digunakan untuk pemrosesan file lainnya, sehingga kode python ini masih bagus.

Pertanyaan: Apakah mengkompilasi regex hanya satu kali dan memberikannya kepada semua pekerja akan meningkatkan kecepatan? Jawab: Regex pre-compiling TIDAK membantu aplikasi ini. Saya kira alasannya adalah bahwa overhead proses serialisasi dan penciptaan untuk semua pekerja mendominasi.

Satu hal lagi. Apakah pembacaan file CSV paralel bahkan membantu? Apakah disk hambatannya, atau apakah itu CPU? Banyak yang disebut jawaban berperingkat teratas di stackoverflow mengandung kebijaksanaan dev yang umum bahwa Anda hanya perlu satu utas untuk membaca file, terbaik yang bisa Anda lakukan, kata mereka. Apakah mereka yakin?

Mari cari tahu:

HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=16 --balanceFactor=2
11000000

real    0m2.256s
user    0m10.696s
sys 0m19.952s

HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=1 --balanceFactor=1
11000000

real    0m17.380s
user    0m11.124s
sys 0m6.272s

Oh ya, ya itu. Pembacaan file paralel bekerja dengan sangat baik. Nah begitulah!

Ps. Jika beberapa dari Anda ingin tahu, bagaimana jika balanceFactor adalah 2 ketika menggunakan proses pekerja tunggal? Ya, itu mengerikan:

HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=1 --balanceFactor=2
11000000

real    1m37.077s
user    0m12.432s
sys 1m24.700s

Bagian penting dari program python fastread.py:

fileBytes = stat(fileName).st_size  # Read quickly from OS how many bytes are in a text file
startByte, endByte = PartitionDataToWorkers(workers=numProcesses, items=fileBytes, balanceFactor=balanceFactor)
p = Pool(numProcesses)
partialSum = p.starmap(ReadFileSegment, zip(startByte, endByte, repeat(fileName))) # startByte is already a list. fileName is made into a same-length list of duplicates values.
globalSum = sum(partialSum)
print(globalSum)


def ReadFileSegment(startByte, endByte, fileName, searchChar='\n'):  # counts number of searchChar appearing in the byte range
    with open(fileName, 'r') as f:
        f.seek(startByte-1)  # seek is initially at byte 0 and then moves forward the specified amount, so seek(5) points at the 6th byte.
        bytes = f.read(endByte - startByte + 1)
        cnt = len(re.findall(searchChar, bytes)) # findall with implicit compiling runs just as fast here as re.compile once + re.finditer many times.
    return cnt

Def untuk PartitionDataToWorkers hanyalah kode sekuensial biasa. Saya meninggalkannya untuk berjaga-jaga seandainya ada orang lain yang ingin berlatih seperti apa pemrograman paralel. Saya membagikan secara gratis bagian yang lebih sulit: kode paralel yang diuji dan berfungsi, untuk manfaat belajar Anda.

Terima kasih kepada: Proyek H2O open-source, oleh Arno dan Cliff dan staf H2O untuk perangkat lunak dan video instruksinya yang hebat, yang telah memberi saya inspirasi untuk pembaca offset byte paralel kinerja tinggi python murni ini seperti yang ditunjukkan di atas. H2O melakukan pembacaan file paralel menggunakan java, dapat dipanggil oleh program python dan R, dan gila cepat, lebih cepat dari apa pun di planet ini saat membaca file CSV besar.

Geoffrey Anderson
sumber
Potongan paralel adalah apa ini, pada dasarnya. Juga, saya berharap SSD dan Flash adalah satu-satunya perangkat penyimpanan yang kompatibel dengan teknik ini. Spinning HD tidak mungkin kompatibel.
Geoffrey Anderson
1
Bagaimana Anda menjelaskan file disk caching OS?
JamesThomasMoon1979
5

Katrielalex menyediakan cara untuk membuka & membaca satu file.

Namun cara algoritme Anda, ia membaca seluruh file untuk setiap baris file. Itu berarti jumlah keseluruhan membaca file - dan menghitung jarak Levenshtein - akan dilakukan N * N jika N adalah jumlah baris dalam file. Karena Anda khawatir tentang ukuran file dan tidak ingin menyimpannya di memori, saya khawatir tentang runtime kuadratik yang dihasilkan . Algoritme Anda termasuk dalam kelas algoritma O (n ^ 2) yang sering kali dapat ditingkatkan dengan spesialisasi.

Saya menduga Anda sudah mengetahui pertukaran memori versus runtime di sini, tetapi mungkin Anda ingin menyelidiki apakah ada cara yang efisien untuk menghitung beberapa jarak Levenshtein secara paralel. Jika demikian, akan menarik untuk membagikan solusi Anda di sini.

Berapa banyak baris yang dimiliki file Anda, dan pada mesin seperti apa (daya mem & cpu) yang harus dijalankan oleh algoritma Anda, dan apa runtime yang dapat ditoleransi?

Kode akan terlihat seperti:

with f_outer as open(input_file, 'r'):
    for line_outer in f_outer:
        with f_inner as open(input_file, 'r'):
            for line_inner in f_inner:
                compute_distance(line_outer, line_inner)

Tetapi pertanyaannya adalah bagaimana Anda menyimpan jarak (matriks?) Dan dapatkah Anda mendapatkan keuntungan dari mempersiapkan mis. Outer_line untuk diproses, atau menyimpan beberapa hasil sementara untuk digunakan kembali.

cfi
sumber
Maksud saya adalah bahwa posting ini tidak mengandung jawaban atas pertanyaan, hanya beberapa pertanyaan lagi! IMO itu akan lebih cocok sebagai komentar.
Katriel
1
@katriealex: Err. Aneh. Anda memang melihat loop bersarang, memperluas jawaban Anda sendiri agar sesuai dengan pertanyaan aktual? Saya dapat menghapus pertanyaan saya di sini dari jawaban saya, dan ada cukup konten untuk menjamin memberikan ini sebagai - meskipun sebagian - jawaban. Saya juga bisa menerima jika Anda ingin mengedit jawaban Anda sendiri untuk menyertakan contoh loop bersarang - yang secara eksplisit ditanyakan oleh pertanyaan - dan kemudian saya dapat menghapus jawaban saya sendiri dengan senang hati. Tapi downvote adalah sesuatu yang tidak saya dapatkan sama sekali.
cfi
Cukup adil; Saya tidak benar-benar melihat mendemonstrasikan bersarang untuk loop sebagai jawaban atas pertanyaan, tetapi saya kira itu cukup kuat ditargetkan pada pemula. Penghapusan unduhan dihapus.
Katriel
3
#Using a text file for the example
with open("yourFile.txt","r") as f:
    text = f.readlines()
for line in text:
    print line
  • Buka file Anda untuk membaca (r)
  • Baca seluruh file dan simpan setiap baris ke dalam daftar (teks)
  • Loop melalui daftar mencetak setiap baris.

Jika Anda ingin, misalnya, untuk memeriksa garis tertentu dengan panjang lebih dari 10, bekerja dengan apa yang sudah Anda miliki.

for line in text:
    if len(line) > 10:
        print line
loxsat
sumber
1
Bukan yang terbaik untuk pertanyaan ini, tetapi kode ini terutama berguna jika apa yang Anda cari.adalah "slurping" (membaca seluruh file sekaligus). Itu adalah kasus saya dan google membuat saya di sini. +1. Juga, untuk atomicity, atau jika Anda menghabiskan waktu pemrosesan dalam loop mungkin berakhir lebih cepat untuk membaca seluruh file
ntg
1
Juga, tingkatkan sedikit kode: 1. tutup tidak diperlukan setelah dengan: ( docs.python.org/2/tutorial/inputoutput.html , cari "Ini adalah praktik yang baik untuk menggunakan kata kunci dengan ...") 2 . teks dapat diproses setelah file dibaca (ouside dengan loop ....)
ntg
2

Dari dokumentasi python untuk fileinput .input ():

Ini berulang pada baris semua file yang terdaftar sys.argv[1:], default ke sys.stdinjika daftar kosong

lebih lanjut, definisi fungsi adalah:

fileinput.FileInput([files[, inplace[, backup[, mode[, openhook]]]]])

membaca yang tersirat, ini memberitahu saya bahwa itu filesbisa menjadi daftar sehingga Anda bisa memiliki sesuatu seperti:

for each_line in fileinput.input([input_file, input_file]):
  do_something(each_line)

Lihat di sini untuk informasi lebih lanjut

KevinDTimm
sumber
2

Saya akan sangat menyarankan tidak menggunakan memuat file default karena sangat lambat. Anda harus melihat ke fungsi numpy dan fungsi IOpro (mis. Numpy.loadtxt ()).

http://docs.scipy.org/doc/numpy/user/basics.io.genfromtxt.html

https://store.continuum.io/cshop/iopro/

Kemudian Anda dapat memecah operasi berpasangan menjadi beberapa bagian:

import numpy as np
import math

lines_total = n    
similarity = np.zeros(n,n)
lines_per_chunk = m
n_chunks = math.ceil(float(n)/m)
for i in xrange(n_chunks):
    for j in xrange(n_chunks):
        chunk_i = (function of your choice to read lines i*lines_per_chunk to (i+1)*lines_per_chunk)
        chunk_j = (function of your choice to read lines j*lines_per_chunk to (j+1)*lines_per_chunk)
        similarity[i*lines_per_chunk:(i+1)*lines_per_chunk,
                   j*lines_per_chunk:(j+1)*lines_per_chunk] = fast_operation(chunk_i, chunk_j) 

Ini hampir selalu jauh lebih cepat untuk memuat data dalam potongan dan kemudian melakukan operasi matriks di atasnya daripada melakukannya elemen demi elemen !!

John Haberstroh
sumber
0

Perlu sering membaca file besar dari posisi terakhir?

Saya telah membuat skrip yang digunakan untuk memotong file Apache access.log beberapa kali sehari. Jadi saya perlu mengatur kursor posisi pada baris terakhir yang diuraikan selama eksekusi terakhir . Untuk tujuan ini, saya menggunakan file.seek()dan file.seek()metode yang memungkinkan penyimpanan kursor dalam file.

Kode saya:

ENCODING = "utf8"
CURRENT_FILE_DIR = os.path.dirname(os.path.abspath(__file__))

# This file is used to store the last cursor position
cursor_position = os.path.join(CURRENT_FILE_DIR, "access_cursor_position.log")

# Log file with new lines
log_file_to_cut = os.path.join(CURRENT_FILE_DIR, "access.log")
cut_file = os.path.join(CURRENT_FILE_DIR, "cut_access", "cut.log")

# Set in from_line 
from_position = 0
try:
    with open(cursor_position, "r", encoding=ENCODING) as f:
        from_position = int(f.read())
except Exception as e:
    pass

# We read log_file_to_cut to put new lines in cut_file
with open(log_file_to_cut, "r", encoding=ENCODING) as f:
    with open(cut_file, "w", encoding=ENCODING) as fw:
        # We set cursor to the last position used (during last run of script)
        f.seek(from_position)
        for line in f:
            fw.write("%s" % (line))

    # We save the last position of cursor for next usage
    with open(cursor_position, "w", encoding=ENCODING) as fw:
        fw.write(str(f.tell()))
Samuel Dauzon
sumber
-2

Cara terbaik untuk membaca file besar, baris demi baris adalah dengan menggunakan fungsi enumerasi python

with open(file_name, "rU") as read_file:
    for i, row in enumerate(read_file, 1):
        #do something
        #i in line of that line
        #row containts all data of that line
Anurag Misra
sumber
3
Mengapa menggunakan penghitungan lebih baik? Satu-satunya manfaat dari jawaban yang diterima adalah bahwa Anda mendapatkan indeks, yang OP tidak perlu dan Anda membuat kode lebih mudah dibaca.
fuyas