Cómo escribir una gran cantidad de datos en un archivo tar en python sin usar un archivo temporal

Escribí un pequeño módulo criptográfico en Python cuya tarea es cifrar un archivo y colocar el resultado en un archivo tar. El archivo original para cifrar puede ser bastante grande, pero eso no es un problema porque mi progtwig solo necesita trabajar con un pequeño bloque de datos a la vez, que puede cifrarse sobre la marcha y almacenarse.

Estoy buscando una manera de evitar hacerlo en dos pases, primero escribiendo todos los datos en un archivo temporal y luego insertando el resultado en un archivo tar.

Básicamente, hago lo siguiente (donde generator_encryptor es un generador simple que produce fragmentos de datos leídos de sourcefile). :

t = tarfile.open("target.tar", "w") tmp = file('content', 'wb') for chunk in generator_encryptor("sourcefile"): tmp.write(chunks) tmp.close() t.add(content) t.close() 

Me molesta un poco tener que usar un archivo temporal, ya que al archivarlo debería ser fácil escribir bloques directamente en el archivo tar, pero recolectando todos los fragmentos en una sola cadena y usando algo como t.addfile (‘contenido’, StringIO ( bigcipheredstring) parece excluido porque no puedo garantizar que tenga suficiente memoria como para la antigua bigcipheredstring.

¿Alguna pista de cómo hacer eso?

Puede crear un objeto propio similar a un archivo y pasarlo a TarFile.addfile. Su objeto tipo archivo generará los contenidos cifrados sobre la marcha en el método fileobj.read ().

Eh ¿No puedes usar el módulo de subproceso para pasar una tubería hasta tar? De esa manera, ningún archivo temporal debería ser necesario. Por supuesto, esto no funcionará si no puede generar sus datos en partes lo suficientemente pequeñas como para que quepan en la RAM, pero si tiene ese problema, entonces el problema no es tar.

Básicamente, usar un objeto similar a un archivo y pasarlo a TarFile.addfile hace el truco, pero todavía hay algunos problemas pendientes.

  • Necesito saber el tamaño del archivo encriptado completo al principio
  • la forma en que el acceso de tarfile al método de lectura es tal que el objeto personalizado similar a un archivo siempre debe devolver buffers de lectura completos, o suponer que es el final del archivo. Esto conduce a una copia de búfer realmente ineficiente en el código del método de lectura, pero es eso o cambiar el módulo de archivo tar.

El código resultante está debajo, básicamente tuve que escribir una clase de envoltorio que transforme mi generador existente en un objeto similar a un archivo. También agregué la clase GeneratorEncrypto en mi ejemplo para hacer que el código sea completo. Puede observar que tiene un método len que devuelve la longitud del archivo escrito (pero comprenda que es solo un marcador de posición ficticio que no hace nada útil).

 import tarfile class GeneratorEncryptor(object): """Dummy class for testing purpose The real one perform on the fly encryption of source file """ def __init__(self, source): self.source = source self.BLOCKSIZE = 1024 self.NBBLOCKS = 1000 def __call__(self): for c in range(0, self.NBBLOCKS): yield self.BLOCKSIZE * str(c%10) def __len__(self): return self.BLOCKSIZE * self.NBBLOCKS class GeneratorToFile(object): """Transform a data generator into a conventional file handle """ def __init__(self, generator): self.buf = '' self.generator = generator() def read(self, size): chunk = self.buf while len(chunk) < size: try: chunk = chunk + self.generator.next() except StopIteration: self.buf = '' return chunk self.buf = chunk[size:] return chunk[:size] t = tarfile.open("target.tar", "w") tmp = file('content', 'wb') generator = GeneratorEncryptor("source") ti = t.gettarinfo(name = "content") ti.size = len(generator) t.addfile(ti, fileobj = GeneratorToFile(generator)) t.close() 

Supongo que necesita comprender cómo funciona el formato de alquitrán y manejar la escritura de alquitrán usted mismo. Tal vez esto puede ser útil?

http://mail.python.org/pipermail/python-list/2001-August/100796.html