Użyłem hashliba (który zastępuje md5 w Pythonie 2.6 / 3.0) i działało dobrze, jeśli otworzyłem plik i włączyłem jego zawartość do hashlib.md5()
funkcji.
Problem dotyczy bardzo dużych plików, których rozmiar może przekraczać rozmiar pamięci RAM.
Jak uzyskać skrót MD5 pliku bez ładowania całego pliku do pamięci?
Odpowiedzi:
Podziel plik na 8192-bajtowe fragmenty (lub inną wielokrotność 128 bajtów) i podaj je kolejno do MD5
update()
.Wykorzystuje to fakt, że MD5 ma 128-bajtowe bloki podsumowania (8192 to 128 × 64). Ponieważ nie odczytujesz całego pliku do pamięci, nie zajmie to więcej niż 8192 bajtów pamięci.
W Python 3.8+ możesz to zrobić
źródło
hashlib.blake2b
zamiastmd5
. W przeciwieństwie do MD5 BLAKE2 jest bezpieczny i jeszcze szybszy.Musisz przeczytać plik w kawałkach o odpowiednim rozmiarze:
UWAGA: Upewnij się, że otworzyłeś plik za pomocą „rb” do otwarcia - w przeciwnym razie otrzymasz niewłaściwy wynik.
Aby wykonać cały proces za pomocą jednej metody - użyj czegoś takiego:
Powyższa aktualizacja była oparta na komentarzach Frericha Raabe - przetestowałem to i stwierdziłem, że jest poprawna podczas instalacji systemu Windows w Python 2.7.2
Sprawdziłem wyniki za pomocą narzędzia „jacksum”.
http://www.jonelo.de/java/jacksum/
źródło
rb
doopen
funkcji.hexdigest
zamiastdigest
spowoduje utworzenie szesnastkowego skrótu, który „wygląda” jak większość przykładów skrótów.if len(data) < block_size: break
?open
zawsze otwiera nowy uchwyt pliku z pozycją ustawioną na początek pliku, (chyba że otworzysz plik do dołączenia).Poniżej zamieściłem sugestie z komentarzy. Dziękuję al!
python <3.7
python 3.8 i wyżej
oryginalny post
jeśli zależy Ci na bardziej pythonicznym (nie „while True”) sposobie odczytu pliku, sprawdź ten kod:
Zauważ, że iter () func potrzebuje pustego ciągu bajtów, aby zwrócony iterator zatrzymał się na EOF, ponieważ read () zwraca b '' (nie tylko '').
źródło
128*md5.block_size
zamiast8192
.md5.block_size
.b''
składnia było dla mnie nowe. Wyjaśniono tutaj .Oto moja wersja metody @Piotr Czapla:
źródło
Korzystając z wielu komentarzy / odpowiedzi w tym wątku, oto moje rozwiązanie:
I w końcu,
- Zostało to zbudowane przez społeczność, dziękuję wszystkim za porady / pomysły.
źródło
Przenośne rozwiązanie Python 2/3
Aby obliczyć sumę kontrolną (md5, sha1 itp.), Musisz otworzyć plik w trybie binarnym, ponieważ sumujesz wartości bajtów:
Aby być przenośnym py27 / py3, powinieneś użyć takich
io
pakietów:Jeśli twoje pliki są duże, możesz chcieć przeczytać plik po kawałkach, aby uniknąć przechowywania całej zawartości pliku w pamięci:
Sztuczka polega na tym, aby użyć
iter()
funkcji z wartownikiem (pusty ciąg znaków).Jeśli Twoje pliki są naprawdę duże, może być konieczne wyświetlenie informacji o postępach. Możesz to zrobić, wywołując funkcję zwrotną, która drukuje lub rejestruje obliczoną liczbę bajtów:
źródło
Remiks kodu Bastien Semene, który bierze pod uwagę komentarz Hawkwinga na temat ogólnej funkcji skrótu ...
źródło
nie można dostać to md5 bez przeczytania pełnej treści. ale możesz użyć funkcji aktualizacji, aby odczytać zawartość pliku blok po bloku.
m. aktualizacja (a); m.update (b) jest równoważne m.update (a + b)
źródło
Myślę, że następujący kod jest bardziej pythonowy:
źródło
Realizacja zaakceptowanej odpowiedzi dla Django:
źródło
Nie lubię pętli. Na podstawie @Nathan Feger:
źródło
hashlib
API naprawdę nie gra dobrze z resztą Pythona. Na przykład weźmy,shutil.copyfileobj
który ściśle nie działa. Mój następny pomysł tofold
(akareduce
) składanie iterowalnych razem w pojedyncze obiekty. Jak np. Hash.hashlib
nie zapewnia operatorów, co sprawia, że jest to trochę uciążliwe. Niemniej jednak składali tutaj iteracje.źródło
Nie jestem pewien, czy nie ma tu zbyt wiele problemów. Ostatnio miałem problemy z md5 i plikami przechowywanymi jako obiekty BLOB na MySQL, więc eksperymentowałem z różnymi rozmiarami plików i prostym podejściem do Pythona, a mianowicie:
Nie mogłem wykryć zauważalnej różnicy wydajności w zakresie rozmiarów plików od 2Kb do 20Mb, a zatem nie ma potrzeby „dzielenia” haszowania. W każdym razie, jeśli Linux musi przejść na dysk, prawdopodobnie zrobi to co najmniej tak samo, jak zdolność przeciętnego programisty do powstrzymania tego. Tak się złożyło, że problem nie miał nic wspólnego z md5. Jeśli używasz MySQL, nie zapomnij już o funkcjach md5 () i sha1 ().
źródło