Frage

Gibt es eine Möglichkeit, einen String direkt in eine Tarfile zu schreiben?Aus http://docs.python.org/library/tarfile.html Es sieht so aus, als ob nur Dateien hinzugefügt werden können, die bereits in das Dateisystem geschrieben wurden.

War es hilfreich?

Lösung

Ich würde sagen, es ist möglich, durch das Spiel mit TarInfo e TarFile.addfile eine StringIO als Fileobject übergeben.

Sehr rau, aber Werke

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()

Andere Tipps

Wie Stefano wies darauf hin, können Sie TarFile.addfile und StringIO verwenden.

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()

Sie wollen wahrscheinlich auch andere Felder von tarinfo (z mtime, uname etc.) als auch füllen.

Ich fand diese Suche wie in Django dienen ein nur im Speicher TGZ-Archiv erstellt, kann jemand anderes meinen Code nützlich finden:

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

Nur für das Protokoll:
StringIO-Objekte haben eine .len-Eigenschaft.
Es ist nicht nötig, „seeke(0)“ und „len(foo.buf)“ auszuführen.
Sie müssen nicht die gesamte Zeichenfolge bereithalten, um len() auszuführen, oder Gott bewahre, Sie müssen die Abrechnung selbst durchführen.

(Vielleicht war das zum Zeitpunkt der Erstellung des OP noch nicht der Fall.)

Sie haben TarInfo Objekte und die AddFile Methode anstelle der üblichen Anbaumethode verwenden:

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))

In meinem Fall wollte ich aus einer vorhandenen tar-Datei lesen, einige Daten zu den Inhalten anzuhängen, und schreiben Sie es in eine neue Datei. So etwas wie:

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)

Zusatzcode ist erforderlich für Verzeichnisse und Links Handhabung.

Die Lösung in Python 3 verwendet io.BytesIO. Achten Sie darauf, TarInfo.size auf die Länge des Bytes zu setzen, nicht die Länge der Zeichenfolge.

eine einzelne Saite gegeben, ist die einfachste Lösung .encode() darauf zu nennen Bytes zu erhalten. In der heutigen Zeit wollen Sie wahrscheinlich UTF-8, aber wenn der Empfänger eine bestimmte Codierung, wie ASCII erwartet (das heißt kein Multi-Byte-Zeichen), dann ist das stattdessen verwendet werden.

import io
import tarfile

data = 'hello\n'.encode('utf8')
info = tarfile.TarInfo(name='foo.txt')
info.size = len(data)

with tarfile.TarFile('test.tar', 'w') as tar:
    tar.addfile(info, io.BytesIO(data))

Wenn Sie wirklich brauchen eine beschreibbare string Puffer, ähnlich wie die akzeptierten Antwort von @Stefano Borini für Python 2 ist, dann ist die Lösung io.TextIOWrapper über einen darunter liegenden io.BytesIO Puffer verwenden.

import io
import tarfile

textIO = io.TextIOWrapper(io.BytesIO(), encoding='utf8')
textIO.write('hello\n')
bytesIO = textIO.detach()
info = tarfile.TarInfo(name='foo.txt')
info.size = bytesIO.tell()

with tarfile.TarFile('test.tar', 'w') as tar:
    bytesIO.seek(0)
    tar.addfile(info, bytesIO)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top