He usado hashlib (que reemplaza md5 en Python 2.6 / 3.0) y funcionó bien si abrí un archivo y puse su contenido en hashlib.md5()
función.
El problema es con archivos muy grandes que sus tamaños podrían exceder el tamaño de RAM.
¿Cómo obtener el hash MD5 de un archivo sin cargar todo el archivo en la memoria?
Respuestas:
Divida el archivo en fragmentos de 8192 bytes (o algún otro múltiplo de 128 bytes) y aliméntelos a MD5 consecutivamente con
update()
.Esto aprovecha el hecho de que MD5 tiene bloques de resumen de 128 bytes (8192 es 128 × 64). Como no está leyendo todo el archivo en la memoria, esto no utilizará mucho más de 8192 bytes de memoria.
En Python 3.8+ puedes hacer
fuente
hashlib.blake2b
lugar demd5
. A diferencia de MD5, BLAKE2 es seguro y es aún más rápido.Debe leer el archivo en fragmentos de tamaño adecuado:
NOTA: Asegúrese de abrir su archivo con el 'rb' al abierto; de lo contrario, obtendrá el resultado incorrecto.
Entonces, para hacer todo en un método, use algo como:
La actualización anterior se basó en los comentarios proporcionados por Frerich Raabe, y probé esto y descubrí que era correcto en mi instalación de Windows Python 2.7.2
Verifiqué los resultados con la herramienta 'jacksum'.
http://www.jonelo.de/java/jacksum/
fuente
rb
a laopen
función.hexdigest
lugar dedigest
producirá un hash hexadecimal que "se ve" como la mayoría de los ejemplos de hashes.if len(data) < block_size: break
?open
siempre abre un nuevo identificador de archivo con la posición establecida al inicio del archivo (a menos que abra un archivo para agregarlo).A continuación he incorporado sugerencias de comentarios. Gracias al!
pitón <3.7
Python 3.8 y superior
publicación original
si le interesa más la forma pitónica (no 'while True') de leer el archivo, verifique este código:
Tenga en cuenta que la función iter () necesita una cadena de bytes vacía para que el iterador devuelto se detenga en EOF, ya que read () devuelve b '' (no solo '').
fuente
128*md5.block_size
lugar de8192
.md5.block_size
.b''
sintaxis era nueva para mí. Explicado aquí .Aquí está mi versión del método de @Piotr Czapla:
fuente
Usando múltiples comentarios / respuestas en este hilo, aquí está mi solución:
Y finalmente,
- Esto ha sido construido por una comunidad, gracias a todos por sus consejos / ideas.
fuente
Una solución portátil Python 2/3
Para calcular una suma de comprobación (md5, sha1, etc.), debe abrir el archivo en modo binario, ya que sumará los valores de bytes:
Para ser portátil py27 / py3, debe usar los
io
paquetes, de esta manera:Si sus archivos son grandes, puede preferir leer el archivo por partes para evitar almacenar todo el contenido del archivo en la memoria:
El truco aquí es usar la
iter()
función con un centinela (la cadena vacía).Si sus archivos son realmente grandes, es posible que también necesite mostrar información de progreso. Puede hacerlo llamando a una función de devolución de llamada que imprime o registra la cantidad de bytes calculados:
fuente
Una remezcla del código Bastien Semene que tiene en cuenta el comentario de Hawkwing sobre la función de hash genérica ...
fuente
no puedes obtener su md5 sin leer el contenido completo. pero puede usar la función de actualización para leer el contenido de los archivos bloque por bloque.
m.actualización (a); m.update (b) es equivalente a m.update (a + b)
fuente
Creo que el siguiente código es más pitónico:
fuente
Implementación de la respuesta aceptada para Django:
fuente
No me gustan los loops. Basado en @Nathan Feger:
fuente
hashlib
la API realmente no funciona bien con el resto de Python. Por ejemplo, tomemosshutil.copyfileobj
que estrechamente no funciona. Mi siguiente idea fuefold
(akareduce
) que pliega iterables en objetos individuales. Como, por ejemplo, un hash.hashlib
no proporciona operadores, lo que hace que esto sea un poco engorroso. Sin embargo estaban doblando un iterables aquí.fuente
No estoy seguro de que no haya demasiado alboroto por aquí. Recientemente tuve problemas con md5 y archivos almacenados como blobs en MySQL, así que experimenté con varios tamaños de archivos y el enfoque directo de Python, a saber:
No pude detectar ninguna diferencia de rendimiento notable con un rango de tamaños de archivo de 2Kb a 20Mb y, por lo tanto, no es necesario 'fragmentar' el hash. De todos modos, si Linux tiene que ir al disco, probablemente lo hará al menos tan bien como la capacidad promedio del programador para evitar que lo haga. Como sucedió, el problema no tenía nada que ver con md5. Si está utilizando MySQL, no olvide las funciones md5 () y sha1 () que ya están allí.
fuente