Quiero que Python lea en el EOF para poder obtener un hash apropiado, ya sea sha1 o md5. Por favor ayuda. Esto es lo que tengo hasta ahora:
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()
hace: leer todo el archivo.read()
método dice?Respuestas:
TL; DR usa búferes para no usar toneladas de memoria.
Llegamos al meollo de su problema, creo, cuando consideramos las implicaciones de memoria de trabajar con archivos muy grandes . No queremos que este chico malo agite 2 gigas de RAM para un archivo de 2 gigabytes, así que, como señala Pasztorpisti , ¡tenemos que lidiar con esos archivos más grandes en trozos!
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()))
Lo que hemos hecho es que estamos actualizando nuestros hash de este chico malo en trozos de 64 kb a medida que avanzamos con el práctico método de actualización de hashlib . ¡De esta manera usamos mucha menos memoria que los 2 GB que se necesitarían para hash al tipo de una vez!
Puedes probar esto con:
$ mkfile 2g bigfile $ python hashes.py bigfile MD5: a981130cf2b7e09f4686dc273cf7187e SHA1: 91d50642dd930e9542c39d36f0516d45f4e1af0d $ md5 bigfile MD5 (bigfile) = a981130cf2b7e09f4686dc273cf7187e $ shasum bigfile 91d50642dd930e9542c39d36f0516d45f4e1af0d bigfile
¡Espero que ayude!
Además, todo esto se describe en la pregunta vinculada en el lado derecho: Obtenga hash MD5 de archivos grandes en Python
¡Apéndice!
En general, al escribir Python, ayuda a acostumbrarse a seguir pep-8 . Por ejemplo, en Python las variables suelen estar separadas por guiones bajos, no camelCased. Pero eso es solo estilo y nadie realmente se preocupa por esas cosas, excepto las personas que tienen que leer mal estilo ... que podría ser usted leyendo este código dentro de unos años.
fuente
BUF_SIZE
?shasum
binarios. La otra respuesta que se enumera a continuación (la que usa memoryview) es compatible con otras herramientas de hash.Para el cálculo correcto y eficiente del valor hash de un archivo (en Python 3):
'b'
al modo de archivo ) para evitar problemas de codificación de caracteres y conversión de final de línea.readinto()
para evitar la agitación del búfer.Ejemplo:
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()
fuente
resource.getpagesize
Sería de alguna utilidad aquí, si quisiéramos intentar optimizarlo de forma algo dinámica? ¿Y sobre quémmap
?Yo propondría simplemente:
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()
Todas las demás respuestas aquí parecen complicarse demasiado. Python ya está almacenando en búfer al leer (de manera ideal, o configura ese almacenamiento en búfer si tiene más información sobre el almacenamiento subyacente) y, por lo tanto, es mejor leer en fragmentos que la función hash encuentra ideal, lo que lo hace más rápido o al menos menos intensivo en CPU para calcular la función hash. Entonces, en lugar de deshabilitar el almacenamiento en búfer e intentar emularlo usted mismo, utiliza el almacenamiento en búfer de Python y controla lo que debería controlar: lo que el consumidor de sus datos encuentra ideal, el tamaño del bloque hash.
fuente
hash.block_size
se documenta como el 'tamaño de bloque interno del algoritmo hash'. Hashlib no lo encuentra ideal . Nada en la documentación del paquete sugiere queupdate()
prefierahash.block_size
una entrada de tamaño. No usa menos CPU si lo llamas así. Sufile.read()
llamada conduce a muchas creaciones de objetos innecesarios y copias superfluas desde el búfer de archivo a su nuevo objeto de bytes de trozos.block_size
trozos. Si no los proporciona en esos fragmentos, deben almacenarse en búfer y esperar a que aparezcan suficientes datos, o dividir los datos dados en fragmentos internamente. Entonces, puede manejar eso en el exterior y luego simplificar lo que sucede internamente. Encuentro este ideal. Ver por ejemplo: stackoverflow.com/a/51335622/252025block_size
es mucho más pequeño que cualquier tamaño útil de lectura. Además, cualquier bloque útil y tamaño de lectura son potencias de dos. Por tanto, el tamaño de lectura es divisible por el tamaño de bloque para todas las lecturas excepto posiblemente la última. Por ejemplo, el tamaño del bloque sha256 es de 64 bytes. Eso significa queupdate()
es capaz de procesar directamente la entrada sin ningún búfer hasta un múltiplo deblock_size
. Por lo tanto, solo si la última lectura no es divisible por el tamaño del bloque, debe almacenar en búfer hasta 63 bytes, una vez. Por lo tanto, su último comentario es incorrecto y no respalda las afirmaciones que hace en su respuesta.He programado un módulo que puede procesar archivos grandes con diferentes algoritmos.
Utilice el módulo así:
from py_essentials import hashing as hs hash = hs.fileChecksum("path/to/the/file.txt", "sha256")
fuente
Aquí hay una solución POSIX de Python 3 (¡no Windows!) Que se utiliza
mmap
para mapear el objeto en la memoria.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()
fuente
mmap
en este escenario?bytes
objetos en la memoria y llamanread
demasiadas o muy pocas veces. Esto asignará el archivo directamente a la memoria virtual y lo codificará desde allí: el sistema operativo puede asignar el contenido del archivo directamente desde la memoria caché del búfer al proceso de lectura. Esto significa que esto podría ser más rápido por un factor significativo sobre esteimport 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)
fuente
echo $USER_INPUT | md5sum > encrypted.txt && cat encrypted.txt
que no se ocupa del hash de archivos, especialmente no con los grandes.