2009-09-16 5 views
6

, siempre que sepamos que todo el archivo se cargará en la memoria y podemos permitirlo, cuáles son los inconvenientes (si los hay) o las limitaciones (si corresponde) de cargar un archivo completo (posiblemente un archivo binario) en una python variable. Si esto es técnicamente posible, ¿debería evitarse esto, y por qué?¿Podemos usar una variable de python para contener un archivo completo?

En cuanto al tamaño del archivo, ¿a qué tamaño máximo debe limitarse esta solución? Y por qué ?

El código de carga real podría ser el propuesto en this stackoverflow entry.

Código de la muestra es:

def file_get_contents(filename): 
    with open(filename) as f: 
     return f.read() 

content = file_get_contents('/bin/kill') 

... code manipulating 'content' ... 

[EDIT] manipulación de código que viene a la mente (pero no es tal el caso) está lista/operadores de cadenas estándar (entre corchetes, '+' signos) o un trozo de cuerda operadores ('len', 'in' operator, 'count', 'endswith'/'startswith', 'split', 'translation' ...).

Respuesta

6

Si bien ha recibido buenas respuestas, parece que nadie ha respondido esta parte de su pregunta (como suele ocurrir cuando hace muchas preguntas en una pregunta; -) ...:

respecto a las preocupaciones de tamaño de archivo, a lo tamaño máximo de esta solución debe ser limitada ?. Y por qué ?

Lo más importante es, la cantidad de RAM física puede este proceso específico de Python en realidad uso (lo que se conoce como un "conjunto de trabajo"), sin penalizar indebidamente otros aspectos del rendimiento del sistema en general. Si excede la RAM física para su "conjunto de trabajo", estará paginating e intercambiando dentro y fuera del disco, y su rendimiento puede degradarse rápidamente (hasta un estado conocido como "thrashing"), básicamente, todos los ciclos disponibles van a la tareas de entrada y salida de páginas, y cantidades insignificantes de trabajo real realmente pueden hacerse).

De ese total, una cantidad razonablemente modesta (digamos unos pocos MB como máximo, en general) probablemente se utilizará con código ejecutable (archivos ejecutables propios de Python, DLL o .so) y bytecode y soporte general las estructuras de datos que se necesitan activamente en la memoria; en una máquina moderna típica que no está haciendo otras tareas importantes o urgentes, casi puede ignorar esta sobrecarga en comparación con los gigabytes de RAM que tiene disponibles en general (aunque la situación podría ser diferente en los sistemas integrados, etc.).

Todo lo demás está disponible para sus datos, que incluye este archivo que está leyendo en la memoria, así como cualquier otra estructura de datos significativa. Las "modificaciones" de los datos del archivo normalmente pueden tomar (transitoriamente) el doble de memoria que el tamaño del contenido del archivo (si lo mantiene en una cadena); más, por supuesto, si está guardando una copia del datos antiguos, así como hacer nuevas copias/versiones modificadas.

Por lo tanto, para el uso de "solo lectura" en una máquina moderna típica de 32 bits con, digamos, 2GB de RAM en general, leer en la memoria (digamos) 1.5 GB no debería ser un problema; pero tendrá que ser sustancialmente menor a 1 GB si está haciendo "modificaciones" (¡y aún menos si tiene otras estructuras de datos importantes en la memoria!). Por supuesto, en un servidor dedicado con una versión de 64 bits de Python, un sistema operativo de 64 bits y 16 GB de RAM, los límites prácticos antes eran muy diferentes, más o menos en proporción a la cantidad muy diferente de RAM disponible de hecho.

Por ejemplo, el texto de la Biblia King James como descargable here (descomprimido) es de aproximadamente 4.4 MB; entonces, en una máquina con 2 GB de RAM, puede guardar alrededor de 400 copias ligeramente modificadas en la memoria (si nada más está solicitando memoria), pero, en una máquina con 16 GB de RAM (disponible y direccionable), podría mantén bien más de 3000 de esas copias.

11
  • Sí, se puede
  • El único inconveniente es el uso de memoria, y posiblemente también la velocidad si el archivo es grande.
  • El tamaño del archivo debe limitarse a la cantidad de espacio que tiene en la memoria.

En general, hay mejores formas de hacerlo, pero para los scripts únicos en los que usted sabe que la memoria no es un problema, seguro.

3

El único problema que puede encontrar es el consumo de memoria: las cadenas en Python son inmutables. Así que cuando se necesita cambiar un byte, es necesario copiar la vieja cadena:

new = old[0:pos] + newByte + old[pos+1:] 

Esto necesita hasta tres veces la memoria de old.

En lugar de una cadena, puede usar array. Estos ofrecen un rendimiento mucho mejor si necesita modificar los contenidos y puede crearlos fácilmente a partir de una cadena.

4
with open(filename) as f: 

Esto solo funciona en Python 2.x en Unix. No hará lo que espera en Python 3.xo en Windows, ya que ambos establecen una fuerte distinción entre el texto y los archivos binarios. Es mejor especificar que el archivo es binario, como esto:

with open(filename, 'rb') as f: 

Esto desactivará la conversión CR/LF del sistema operativo en Windows, y obligará a Python 3.x para devolver una matriz de bytes en lugar de caracteres Unicode.

En cuanto al resto de su pregunta, estoy de acuerdo con la respuesta de Lennart Regebro (sin editar).

0

Sí, puede -siempre que el archivo sea lo suficientemente pequeño-.

Es incluso muy pitónico convertir aún más el retorno de read() a cualquier tipo de contenedor/iterable como, por ejemplo, string.split(), junto con funciones de programación funcional asociadas para continuar tratando el archivo "de una vez".

1

También puede utilizar la función de Python v3:

>>> ''.join(open('htdocs/config.php', 'r').readlines()) 
"This is the first line of the file.\nSecond line of the file" 

Leer más aquí http://docs.python.org/py3k/tutorial/inputoutput.html

+1

ver mis otros comentarios, spam mensajes de edad con respuestas duplicadas no es constructivo. – Kev

Cuestiones relacionadas