print bytearray python
Python cómo calcular una suma de comprobación simple tan rápido como zlib.adler32 (2)
Deseo calcular una suma de comprobación simple: simplemente agregando los valores de todos los bytes.
La forma más rápida que encontré es:
checksum = sum([ord(c) for c in buf])
Pero para los datos de 13 Mb, tarda 4,4 s: demasiado tiempo (en C, tarda 0,5 s)
Si uso:
checksum = zlib.adler32(buf) & 0xffffffff
lleva 0,8 s, pero el resultado no es el que yo quiero.
Entonces mi pregunta es: ¿hay alguna función, lib o C para incluir en Python 2.6, para calcular una suma de comprobación simple?
Gracias por adelantado, Eric.
Puede usar sum(bytearray(buf))
:
In [1]: buf = b''a''*(13*(1<<20))
In [2]: %timeit sum(ord(c) for c in buf)
1 loops, best of 3: 1.25 s per loop
In [3]: %timeit sum(imap(ord, buf))
1 loops, best of 3: 564 ms per loop
In [4]: %timeit b=bytearray(buf); sum(b)
10 loops, best of 3: 101 ms per loop
Aquí hay una extensión C para Python escrita en Cython , sumbytes.pyx
file:
from libc.limits cimport ULLONG_MAX, UCHAR_MAX
def sumbytes(bytes buf not None):
cdef:
unsigned long long total = 0
unsigned char c
if len(buf) > (ULLONG_MAX // <size_t>UCHAR_MAX):
raise NotImplementedError #todo: implement for > 8 PiB available memory
for c in buf:
total += c
return total
sumbytes
es ~ 10 veces más rápido que la variante de bytearray
:
name time ratio
sumbytes_sumbytes 12 msec 1.00
sumbytes_numpy 29.6 msec 2.48
sumbytes_bytearray 122 msec 10.19
Para reproducir las medidas de tiempo, descargue reporttime.py
y ejecute:
#!/usr/bin/env python
# compile on-the-fly
import pyximport; pyximport.install() # pip install cython
import numpy as np
from reporttime import get_functions_with_prefix, measure
from sumbytes import sumbytes # from sumbytes.pyx
def sumbytes_sumbytes(input):
return sumbytes(input)
def sumbytes_bytearray(input):
return sum(bytearray(input))
def sumbytes_numpy(input):
return np.frombuffer(input, ''uint8'').sum() # @root''s answer
def main():
funcs = get_functions_with_prefix(''sumbytes_'')
buf = ''''.join(map(unichr, range(256))).encode(''latin1'') * (1 << 16)
measure(funcs, args=[buf])
main()
Use numpy.frombuffer(buf, "uint8").sum()
, parece ser aproximadamente 70 veces más rápido que su ejemplo:
In [9]: import numpy as np
In [10]: buf = b''a''*(13*(1<<20))
In [11]: sum(bytearray(buf))
Out[11]: 1322254336
In [12]: %timeit sum(bytearray(buf))
1 loops, best of 3: 253 ms per loop
In [13]: np.frombuffer(buf, "uint8").sum()
Out[13]: 1322254336
In [14]: %timeit np.frombuffer(buf, "uint8").sum()
10 loops, best of 3: 36.7 ms per loop
In [15]: %timeit sum([ord(c) for c in buf])
1 loops, best of 3: 2.65 s per loop