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.
Jawaban:
Cara Pythonic yang benar dan sepenuhnya membaca file adalah sebagai berikut:
The
with
pernyataan menangani pembukaan dan penutupan file, termasuk jika eksepsi dimunculkan di blok batin. Thefor line in f
memperlakukan file objekf
sebagai iterable, yang secara otomatis menggunakan buffered I / O dan manajemen memori sehingga Anda tidak perlu khawatir tentang file besar.sumber
for line in f:
kerjanya? Maksud saya, bagaimana pengulangan objek file bisa dilakukan?__iter__
, yang memberitahukan apa yang harus dilakukan. Objek file mendefinisikan metode khusus ini untuk mengembalikan iterator melewati garis. (Secara kasar.)Dua cara efisien memori dalam urutan peringkat (pertama adalah yang terbaik) -
with
- didukung dari python 2.5 dan di atasnyayield
jika Anda benar-benar ingin memiliki kontrol atas berapa banyak yang harus dibaca1. penggunaan
with
with
adalah cara pythonic yang bagus dan efisien untuk membaca file besar. Keuntungan - 1) objek file secara otomatis ditutup setelah keluar dariwith
blok eksekusi. 2) penanganan eksepsi di dalamwith
blok. 3) memorifor
loop berulang melaluif
objek file baris demi baris. secara internal memang buffered IO (untuk dioptimalkan pada operasi IO yang mahal) dan manajemen memori.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.
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:
Ketika ini dilakukan, bagaimanapun,
readlines()
fungsi (sama berlaku untukread()
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 menggunakanfileinput
modul, sebagai berikut:yang
fileinput.input()
panggilan membaca garis berurutan, tetapi tidak menjaga mereka dalam memori setelah mereka telah membaca atau bahkan hanya jadi ini, karenafile
di python adalah iterable.Referensi
sumber
for line in open(...).readlines(): <do stuff>
. Mengapa kamu akan?! Anda baru saja kehilangan semua manfaat dari Ierator buffered pintar Python yang tidak bermanfaat.readlines
dan menjelaskan mengapa itu bukan hal yang baik untuk dilakukan (karena membaca file ke dalam memori), kemudian menjelaskan apa yang dilakukanfileinput
modul 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.Untuk menghapus baris baru:
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:
open(file_path, mode='rU')
- diperlukan [terima kasih @Dave ]open(file_path, mode='rU')
- opsionalopen(file_path, newline=None)
- opsionalThe
newline
Parameter hanya didukung dengan Python 3 dan default untukNone
. Themode
parameter default untuk'r'
semua kasus. TheU
sudah ditinggalkan di Python 3. Dalam Python 2 pada Windows mekanisme lain muncul untuk menerjemahkan\r\n
ke\n
.Docs:
Untuk melestarikan terminator jalur asli:
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.
sumber
open(file_path, 'rU')
mengaktifkan baris baru universal.ini adalah cara yang mungkin untuk membaca file dengan python:
itu tidak mengalokasikan daftar lengkap. Iterates melewati garis.
sumber
with open(input_file) as f:
. Ini menghemat Andaf.close()
dan memastikan Anda tidak sengaja lupa untuk menutupnya. Mencegah kebocoran memori dan semuanya, cukup penting saat membaca file.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.
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.
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:
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:
Bagian penting dari program python fastread.py:
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.
sumber
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:
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.
sumber
Jika Anda ingin, misalnya, untuk memeriksa garis tertentu dengan panjang lebih dari 10, bekerja dengan apa yang sudah Anda miliki.
sumber
Dari dokumentasi python untuk fileinput .input ():
lebih lanjut, definisi fungsi adalah:
membaca yang tersirat, ini memberitahu saya bahwa itu
files
bisa menjadi daftar sehingga Anda bisa memiliki sesuatu seperti:Lihat di sini untuk informasi lebih lanjut
sumber
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:
Ini hampir selalu jauh lebih cepat untuk memuat data dalam potongan dan kemudian melakukan operasi matriks di atasnya daripada melakukannya elemen demi elemen !!
sumber
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()
danfile.seek()
metode yang memungkinkan penyimpanan kursor dalam file.Kode saya:
sumber
Cara terbaik untuk membaca file besar, baris demi baris adalah dengan menggunakan fungsi enumerasi python
sumber