2009-04-11 7 views

Respuesta

28

Yo diría que es posible, jugando con TarInfo e TarFile.addfile pasando un StringIO como un objeto de archivo.

muy difícil, pero funciona

import tarfile 
import StringIO 

tar = tarfile.TarFile("test.tar","w") 

string = StringIO.StringIO() 
string.write("hello") 
string.seek(0) 
info = tarfile.TarInfo(name="foo") 
info.size=len(string.buf) 
tar.addfile(tarinfo=info, fileobj=string) 

tar.close() 
+1

Puedes simplemente decir StringIO.StringIO ("hola") para reemplazar la escritura y la búsqueda. – misha

+0

es el procedimiento similar a los objetos python3 y bytesIO? – proteneer

+2

@proteneer: Creo que en python 3 el método seek te da una longitud binaria, mientras que internamente usa la cadena '' 'len()' '' función, por lo que la función '' 'tarfile.copyfileobj''' fallará con '' 'raise OSError (" fin del archivo alcanzado ")' '' – luckydonald

14

Como se señaló Stefano, puede utilizar TarFile.addfile y StringIO.

import tarfile, StringIO 

data = 'hello, world!' 

tarinfo = tarfile.TarInfo('test.txt') 
tarinfo.size = len(data) 

tar = tarfile.open('test.tar', 'a') 
tar.addfile(tarinfo, StringIO.StringIO(data)) 
tar.close() 

es probable que desee para llenar otros campos de tarinfo (por ejemplo mtime, uname etc.) también.

+0

es el "Como señaló Stefano" una edición? De lo contrario, no veo lo que estás haciendo de manera diferente. Gracias por la respuesta de todos modos. – gatoatigrado

+0

Creo que Stefano no ha publicado ningún código en el momento en que escribí mi respuesta, solo señaló que se pueden usar TarFile.addfile y StringIO. Mi memoria es un poco borrosa, sin embargo. – avakar

+0

FWIW, sí, la información detallada de @ Stefano se agregó en [una edición] (http://stackoverflow.com/posts/740839/revisions) después de que usted escribió esto. La otra respuesta diciendo que lo mismo también entró casi simultáneamente. – mattdm

2

usted tiene que utilizar objetos TarInfo y el método AddFile en lugar del método add habitual:

from StringIO import StringIO 
from tarfile import open, TarInfo 

s = "Hello World!" 
ti = TarInfo("test.txt") 
ti.size = len(s) 

tf = open("testtar.tar", "w") 
tf.addfile(ti, StringIO(s)) 
2

En mi caso quería leer desde un archivo tar existente, añadir algunos datos a los contenidos, y escribir a un nuevo archivo. Algo como:

for ti in tar_in: 
    buf_in = tar.extractfile(ti) 
    buf_out = io.BytesIO() 
    size = buf_out.write(buf_in.read()) 
    size += buf_out.write(other data) 
    buf_out.seek(0) 
    ti.size = size 
    tar_out.addfile(ti, fileobj=buf_out) 

Se necesita un código adicional para manejar directorios y enlaces.

2

Solo para el registro:
objetos StringIO tienen una propiedad .len.
No hay necesidad de buscar (0) y do len (foo.buf)
No hay necesidad de mantener toda la cadena para hacer len(), o Dios no lo permita, haga la contabilidad usted mismo.

(Tal vez no lo hizo en el momento de la OP fue escrito.)

6

Me encontraron esta buscando la forma de servir en una Django acaba de crear en la memoria .tgz archivo, puede ser alguien más va a encontrar mi código muy útil:

import tarfile 
from io import BytesIO 


def serve_file(request): 
    out = BytesIO() 
    tar = tarfile.open(mode = "w:gz", fileobj = out) 
    data = 'lala'.encode('utf-8') 
    file = BytesIO(data) 
    info = tarfile.TarInfo(name="1.txt") 
    info.size = len(data) 
    tar.addfile(tarinfo=info, fileobj=file) 
    tar.close() 

    response = HttpResponse(out.getvalue(), content_type='application/tgz') 
    response['Content-Disposition'] = 'attachment; filename=myfile.tgz' 
    return response 
Cuestiones relacionadas