Chcę, aby Python czytał do EOF, aby uzyskać odpowiedni skrót, niezależnie od tego, czy jest to sha1 czy md5. Proszę pomóż. Oto, co mam do tej pory:
import hashlib
inputFile = raw_input("Enter the name of the file:")
openedFile = open(inputFile)
readFile = openedFile.read()
md5Hash = hashlib.md5(readFile)
md5Hashed = md5Hash.hexdigest()
sha1Hash = hashlib.sha1(readFile)
sha1Hashed = sha1Hash.hexdigest()
print "File Name: %s" % inputFile
print "MD5: %r" % md5Hashed
print "SHA1: %r" % sha1Hashed
file.read()
robi - przeczytaj cały plik.read()
metody mówi?Odpowiedzi:
TL; DR używają buforów, aby nie używać ton pamięci.
Myślę, że dochodzimy do sedna twojego problemu, gdy rozważymy implikacje pamięciowe pracy z bardzo dużymi plikami . Nie chcemy, aby ten zły chłopiec przerzucił 2 gigabajty pamięci RAM dla pliku o wielkości 2 gigabajtów, więc jak wskazuje pasztorpisti , musimy poradzić sobie z większymi plikami w kawałkach!
import sys import hashlib # BUF_SIZE is totally arbitrary, change for your app! BUF_SIZE = 65536 # lets read stuff in 64kb chunks! md5 = hashlib.md5() sha1 = hashlib.sha1() with open(sys.argv[1], 'rb') as f: while True: data = f.read(BUF_SIZE) if not data: break md5.update(data) sha1.update(data) print("MD5: {0}".format(md5.hexdigest())) print("SHA1: {0}".format(sha1.hexdigest()))
To, co zrobiliśmy, to aktualizowanie naszych skrótów tego złego chłopca w fragmentach 64kb, wraz z poręczną metodą aktualizacji hashlib . W ten sposób zużywamy o wiele mniej pamięci niż 2 GB potrzebne do zhaszowania faceta na raz!
Możesz to sprawdzić za pomocą:
$ mkfile 2g bigfile $ python hashes.py bigfile MD5: a981130cf2b7e09f4686dc273cf7187e SHA1: 91d50642dd930e9542c39d36f0516d45f4e1af0d $ md5 bigfile MD5 (bigfile) = a981130cf2b7e09f4686dc273cf7187e $ shasum bigfile 91d50642dd930e9542c39d36f0516d45f4e1af0d bigfile
Mam nadzieję, że to pomoże!
Wszystko to jest również opisane w powiązanym pytaniu po prawej stronie: Pobierz skrót MD5 dużych plików w Pythonie
Uzupełnienie!
Generalnie, pisząc w Pythonie, warto nabrać nawyku podążania za pep-8 . Na przykład w pythonie zmienne są zwykle oddzielane podkreśleniem, a nie camelCased. Ale to tylko styl i nikogo tak naprawdę nie obchodzą te rzeczy, z wyjątkiem ludzi, którzy muszą czytać w złym stylu ... może to być Ty czytasz ten kod za lata.
źródło
BUF_SIZE
?shasum
pliki binarne. Druga odpowiedź wymieniona poniżej (ta wykorzystująca widok pamięci) jest kompatybilna z innymi narzędziami do mieszania.W celu prawidłowego i wydajnego obliczenia wartości skrótu pliku (w Pythonie 3):
'b'
do trybu pliku), aby uniknąć problemów z kodowaniem znaków i konwersją końca linii.readinto()
do zapobiegania ubijaniu buforów.Przykład:
import hashlib def sha256sum(filename): h = hashlib.sha256() b = bytearray(128*1024) mv = memoryview(b) with open(filename, 'rb', buffering=0) as f: for n in iter(lambda : f.readinto(mv), 0): h.update(mv[:n]) return h.hexdigest()
źródło
resource.getpagesize
się tutaj, gdybyśmy chcieli spróbować ją nieco dynamicznie zoptymalizować? A co z tymmmap
?Proponuję po prostu:
def get_digest(file_path): h = hashlib.sha256() with open(file_path, 'rb') as file: while True: # Reading is buffered, so we can read smaller chunks. chunk = file.read(h.block_size) if not chunk: break h.update(chunk) return h.hexdigest()
Wszystkie inne odpowiedzi wydają się zbyt skomplikowane. Python już buforuje podczas odczytu (w idealny sposób lub konfigurujesz buforowanie, jeśli masz więcej informacji o podstawowej pamięci), więc lepiej jest czytać fragmentami, które funkcja skrótu uzna za idealną, co przyspiesza lub co najmniej zmniejsza obciążenie procesora oblicz funkcję skrótu. Więc zamiast wyłączać buforowanie i próbować emulować je samemu, używasz buforowania Pythona i kontrolujesz to, co powinieneś kontrolować: to, co konsument Twoich danych uważa za idealny, rozmiar bloku mieszania.
źródło
hash.block_size
jest udokumentowany tak samo, jak „wewnętrzny rozmiar bloku algorytmu wyznaczania wartości skrótu”. Hashlib nie uważa tego za idealne . Nic w dokumentacji pakietu nie sugeruje, żeupdate()
preferujehash.block_size
dane wejściowe o rozmiarze. Nie zużywa mniej procesora, jeśli tak to nazywasz. Twojefile.read()
wywołanie prowadzi do wielu niepotrzebnych kreacji obiektów i zbędnych kopii z bufora pliku do nowego obiektu porcji bajtów.block_size
fragmentami. Jeśli nie dostarczasz ich w tych fragmentach, muszą buforować i czekać na pojawienie się wystarczającej ilości danych lub wewnętrznie podzielić dane na porcje. Możesz więc poradzić sobie z tym na zewnątrz, a następnie uprościć to, co dzieje się wewnętrznie. Uważam, że to ideał. Zobacz na przykład: stackoverflow.com/a/51335622/252025block_size
Jest znacznie mniejsza niż wszelkich użytecznych wielkości odczytu. Ponadto wszelkie przydatne rozmiary bloków i odczytów są potęgami dwójki. Tak więc rozmiar odczytu jest podzielny przez rozmiar bloku dla wszystkich odczytów z wyjątkiem być może ostatniego. Na przykład rozmiar bloku sha256 wynosi 64 bajty. Oznacza to, żeupdate()
jest w stanie bezpośrednio przetwarzać dane wejściowe bez buforowania do wielokrotnościblock_size
. Zatem tylko wtedy, gdy ostatni odczyt nie jest podzielny przez rozmiar bloku, musi jednorazowo buforować do 63 bajtów. Dlatego też Twój ostatni komentarz jest niepoprawny i nie potwierdza twierdzeń, które zawarłeś w swojej odpowiedzi.Zaprogramowałem moduł, który jest w stanie haszować duże pliki różnymi algorytmami.
Użyj modułu w następujący sposób:
from py_essentials import hashing as hs hash = hs.fileChecksum("path/to/the/file.txt", "sha256")
źródło
Oto Python 3, rozwiązanie POSIX (nie Windows!), Które używa
mmap
do mapowania obiektu do pamięci.import hashlib import mmap def sha256sum(filename): h = hashlib.sha256() with open(filename, 'rb') as f: with mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ) as mm: h.update(mm) return h.hexdigest()
źródło
mmap
w tym scenariuszu?bytes
obiekty w pamięci i wywołujeread
zbyt wiele lub zbyt mało razy. Spowoduje to zmapowanie pliku bezpośrednio do pamięci wirtualnej i zhaszowanie go stamtąd - system operacyjny może mapować zawartość pliku bezpośrednio z pamięci podręcznej bufora do procesu odczytu. Oznacza to, że może to być znacznie szybsze niż tenimport hashlib user = input("Enter ") h = hashlib.md5(user.encode()) h2 = h.hexdigest() with open("encrypted.txt","w") as e: print(h2,file=e) with open("encrypted.txt","r") as e: p = e.readline().strip() print(p)
źródło
echo $USER_INPUT | md5sum > encrypted.txt && cat encrypted.txt
co nie zajmuje się haszowaniem plików, szczególnie nie z dużymi.