Saya telah menggunakan hashlib (yang menggantikan md5 dengan Python 2.6 / 3.0) dan berfungsi dengan baik jika saya membuka file dan meletakkan kontennya dalam hashlib.md5()
fungsi.
Masalahnya dengan file yang sangat besar ukurannya bisa melebihi ukuran RAM.
Bagaimana cara mendapatkan hash MD5 file tanpa memuat seluruh file ke memori?
Jawaban:
Pecah file menjadi potongan 8192 byte (atau kelipatan 128 byte lainnya) dan berikan mereka ke MD5 secara berturut-turut menggunakan
update()
.Ini mengambil keuntungan dari fakta bahwa MD5 memiliki blok digest 128-byte (8192 adalah 128 × 64). Karena Anda tidak membaca seluruh file ke dalam memori, ini tidak akan menggunakan lebih dari 8192 byte memori.
Dengan Python 3.8+ Anda bisa melakukannya
sumber
hashlib.blake2b
bukanmd5
. Tidak seperti MD5, BLAKE2 aman, dan bahkan lebih cepat.Anda perlu membaca file dalam ukuran yang sesuai:
CATATAN: Pastikan Anda membuka file Anda dengan 'rb' di tempat terbuka - jika tidak, Anda akan mendapatkan hasil yang salah.
Jadi untuk melakukan semuanya dalam satu metode - gunakan sesuatu seperti:
Pembaruan di atas didasarkan pada komentar yang diberikan oleh Frerich Raabe - dan saya mengujinya dan ternyata benar pada instalasi windows Python 2.7.2 saya
Saya memeriksa ulang hasilnya menggunakan alat 'jacksum'.
http://www.jonelo.de/java/jacksum/
sumber
rb
keopen
fungsi tersebut.hexdigest
bukannyadigest
akan menghasilkan hash heksadesimal yang "terlihat" seperti kebanyakan contoh hash.if len(data) < block_size: break
?open
selalu membuka pegangan file baru dengan posisi diatur ke awal file, (kecuali jika Anda membuka file untuk ditambahkan).Di bawah ini saya memasukkan saran dari komentar. Terima kasih, al!
python <3.7
python 3.8 dan di atas
pos asli
jika Anda peduli dengan cara pythonic (no 'while True') yang lebih banyak untuk membaca file, periksa kode ini:
Perhatikan bahwa fungsi iter () membutuhkan string byte kosong agar iterator yang dikembalikan berhenti di EOF, karena read () mengembalikan b '' (bukan hanya '').
sumber
128*md5.block_size
bukan8192
.md5.block_size
.b''
sintaks baru bagiku. Dijelaskan di sini .Inilah versi metode @Piotr Czapla saya:
sumber
Menggunakan beberapa komentar / jawaban di utas ini, berikut adalah solusi saya:
Dan akhirnya,
- Ini dibangun oleh komunitas, terima kasih atas saran / ide Anda.
sumber
Solusi portabel Python 2/3
Untuk menghitung checksum (md5, sha1, dll.), Anda harus membuka file dalam mode biner, karena Anda akan menjumlahkan nilai byte:
Untuk menjadi py27 / py3 portable, Anda harus menggunakan
io
paket, seperti ini:Jika file Anda besar, Anda mungkin lebih suka membaca file dengan potongan untuk menghindari menyimpan seluruh konten file dalam memori:
Kuncinya di sini adalah menggunakan
iter()
fungsi dengan sentinel (string kosong).Jika file Anda sangat besar, Anda mungkin juga perlu menampilkan informasi kemajuan. Anda dapat melakukannya dengan memanggil fungsi panggilan balik yang mencetak atau mencatat jumlah byte yang dihitung:
sumber
Sebuah remix dari kode Bastien Semene yang mempertimbangkan komentar Hawkwing tentang fungsi hashing generik menjadi pertimbangan ...
sumber
Anda tidak bisa mendapatkannya md5 tanpa membaca konten lengkap. tetapi Anda dapat menggunakan fungsi pembaruan untuk membaca konten file blok demi blok.
m.update (a); m.update (b) setara dengan m.update (a + b)
sumber
Saya pikir kode berikut ini lebih pythonic:
sumber
Implementasi jawaban yang diterima untuk Django:
sumber
Saya tidak suka loop. Berdasarkan @Nathan Feger:
sumber
hashlib
s API tidak benar-benar cocok dengan sisa Python. Sebagai contoh mari kita ambilshutil.copyfileobj
yang gagal berfungsi. Ide saya berikutnya adalahfold
(aliasreduce
) yang melipat iterables bersama menjadi objek tunggal. Seperti misalnya hash.hashlib
tidak menyediakan operator yang membuat ini sedikit rumit. Namun demikian melipat iterables di sini.sumber
Saya tidak yakin bahwa tidak ada terlalu banyak keributan di sekitar sini. Saya baru-baru ini punya masalah dengan md5 dan file yang disimpan sebagai gumpalan di MySQL jadi saya bereksperimen dengan berbagai ukuran file dan pendekatan Python langsung, yaitu:
Saya dapat mendeteksi tidak ada perbedaan kinerja yang nyata dengan kisaran ukuran file 2Kb hingga 20Mb dan karenanya tidak perlu 'memotong' hashing. Bagaimanapun, jika Linux harus pergi ke disk, itu mungkin akan melakukannya setidaknya serta kemampuan rata-rata programmer untuk mencegahnya melakukannya. Ketika itu terjadi, masalahnya tidak ada hubungannya dengan MD5. Jika Anda menggunakan MySQL, jangan lupa fungsi md5 () dan sha1 () sudah ada di sana.
sumber