una separar reemplazar por palabras eliminar contar comparar caracteres caracter cadenas cadena python string file-io

separar - Optimización de procesamiento de cadenas Python



python separar string por caracter (2)

Piense en llamar a un proceso externo (grep y similares) para acelerar el procesamiento y reducir el volumen de datos que tiene que manejar dentro de Python.

Otra ruta a seguir sería filtrar o prefiltrar sus datos con una expresión regular compilada, ya que su ciclo interno utiliza el código optimizado de la biblioteca estándar.

También puede probar Cython o similar para los bucles interiores más populares, consulte, por ejemplo, https://books.google.de/books?id=QSsOBQAAQBAJ&dq=high+perf+python&hl=es para obtener más información al respecto.

Últimamente he estado creando un script de Python para extraer datos de archivos de texto grandes (> 1 GB). El problema básicamente se resume en seleccionar líneas de texto del archivo y buscar cadenas desde alguna matriz (esta matriz puede tener hasta 1000 cadenas). El problema aquí es que tengo que encontrar una ocurrencia específica de la cadena, y la cadena puede aparecer un número ilimitado de veces en ese archivo. Además, se requiere algo de decodificación y codificación, lo que además ralentiza el script. El código se ve así:

strings = [a for a in open(''file.txt'')] with open("er.txt", "r") as f: for chunk in f: for s in strings #do search, trimming, stripping ..

Mi pregunta aquí es: ¿hay alguna manera de optimizar esto? Probé el multiprocesamiento, pero ayuda poco (o al menos la forma en que lo implementé). El problema aquí es que estas operaciones de fragmentos no son independientes y la lista de strings se puede modificar durante uno de ellos. Cualquier optimización sería de ayuda (algoritmos de búsqueda de cadenas, lectura de archivos, etc.). Hice todo lo que pude con respecto a la ruptura de bucles, pero todavía funciona bastante lento.


Si puede saber exactamente cómo está codificada la cadena en binario (ASCII, UTF-8), puede mmap todo el archivo en la memoria a la vez; se comportaría exactamente como un bytearray/bytes grande (o str en Python 2) obtenido por file.read() would; entonces tal objeto mmap podría buscarse mediante una expresión regular str (Python 2), o una expresión regular de bytes (Python 3).

El mmap es la solución más rápida en muchos sistemas operativos, porque el mapeo de solo lectura significa que el sistema operativo puede mapear libremente en las páginas cuando están listos; no se requiere espacio de intercambio, porque los datos están respaldados por un archivo. El sistema operativo también puede mapear directamente los datos de la memoria caché del búfer con copia cero, por lo tanto, una ganancia ganar-ganar sobre la lectura desnuda.

Ejemplo:

import mmap import re pattern = re.compile(b''the ultimate answer is ([0-9]+)'') with open("datafile.txt", "rb") as f: # memory-map the file, size 0 means whole file mm = mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ) # PROT_READ only on *nix as the file is not writable for match in pattern.finditer(mm): # process match print("The answer is {}".format(match.group(1).decode(''ascii''))) mm.close()

Ahora, si el datafile.txt contenía el texto:

the ultimate answer is 42

en algún lugar a lo largo de 1 gigabyte de datos, este programa estaría entre las soluciones de python más rápidas para escupir:

The answer is 42

Tenga en cuenta que pattern.finditer también acepta parámetros de start y end que pueden usarse para limitar el rango donde se intenta la coincidencia.

Como señala ivan_pozdeev , esto requiere 1 gigabyte de espacio libre de direcciones virtuales para mapear un archivo de gigabytes (pero no necesariamente 1 gigabyte de RAM), lo que puede ser difícil en un proceso de 32 bits, pero casi con certeza se puede suponer "sin problemas" "en el sistema operativo y CPU de 64 bits. En los procesos de 32 bits, el enfoque sigue funcionando, pero es necesario mapear los archivos grandes en trozos más pequeños, por lo que ahora los bits del sistema operativo y del procesador realmente importan.