5 Stimmen

Pickle-Daten (oder beliebige Daten) in ein Python-Skript einbetten

In Perl hält der Interpreter quasi an, wenn er auf eine Zeile mit

__END__

darin. Dies wird oft verwendet, um beliebige Daten am Ende eines Perl-Skripts einzubetten. Auf diese Weise kann das Perl-Skript Daten abrufen und speichern, die es "in sich selbst" speichert, was sehr schöne Möglichkeiten eröffnet.

In meinem Fall habe ich ein eingelegtes Objekt, das ich irgendwo speichern möchte. Ich kann zwar eine file.pickle-Datei verwenden, aber ich suchte nach einem kompakteren Ansatz (um das Skript leichter verteilen zu können).

Gibt es einen Mechanismus, der es erlaubt, beliebige Daten irgendwie in ein Python-Skript einzubetten?

4voto

Frank Punkte 10276

Mit pickle können Sie auch direkt auf Strings arbeiten.

s = pickle.dumps(obj)
pickle.loads(s)

Wenn Sie das mit """ kombinieren (Strings in dreifachen Anführungszeichen) können Sie problemlos beliebige gepickelte Daten in Ihrer Datei speichern.

3voto

Peter Hansen Punkte 20242

Wenn die Daten nicht besonders groß sind (viele K), würde ich sie einfach mit .encode('base64') kodieren und in eine Zeichenkette mit drei Anführungszeichen einfügen, mit .decode('base64'), um die binären Daten zurückzubekommen, und einem pickle.loads()-Aufruf um sie herum.

0 Stimmen

Warum base64 kodieren, wenn pickle.dumps() bereits standardmäßig ASCII ausgibt?

0 Stimmen

Lester, mehrere Gründe. Haben Sie es mit binären Daten versucht? Es ist viel größer, weil alle Escaping. Außerdem formatiert die Python 2.x str.encode()-Routine die Daten in schönen Zeilen, um die Quelldatei ordentlich zu halten. (Unter 3.x kann man mit str.encode nicht nach base64 kodieren, aber es gibt ein base64-Modul. Sieht so aus, als ob die nette Formatierung jetzt vielleicht eigenen Code erfordert. Beachten Sie auch, dass pickle.dumps() unter 3.x standardmäßig einen Byte-Typ ausgibt, nicht String, obwohl das an sich wahrscheinlich kein Problem ist).

0 Stimmen

Na gut - ich würde mir zu viele Gedanken über die Größe machen, bis ich Leistungsprobleme habe ;-)

2voto

S.Lott Punkte 371691

In Python können Sie """ (Strings in dreifachen Anführungszeichen) verwenden, um lange Textabschnitte in Ihr Programm einzubetten.

In Ihrem Fall sollten Sie jedoch keine Zeit damit verschwenden.

Wenn Sie ein Objekt haben, das Sie gepickelt haben, würden Sie viel, viel glücklicher sein, dass Objekt als Python-Quelle zu entladen und einfach die Quelle enthalten.

El repr Funktion, die auf die meisten Objekte angewendet wird, gibt eine Python-Quelltextversion des Objekts aus. Wenn Sie die Funktion __repr__ für alle Ihre benutzerdefinierten Klassen verwenden, können Sie Ihre Struktur trivialerweise als Python-Source ausgeben.

Wenn Ihre eingelegte Struktur hingegen als Python-Code begann, belassen Sie sie einfach als Python-Code.

0 Stimmen

Zu wenig klar (denke ich): Machen Sie einfach die Klasse __repr__() Methode den Python-Quellcode für einen gültigen Aufruf der Klassenfunktion __init__() Methode, die die zu speichernde Instanz rekonstruieren wird.

2voto

Brian Punkte 1016

Ich habe diesen Code erstellt. Man führt etwas wie python comp.py foofile.tar.gz aus, und es wird decomp.py erstellt, in das der Inhalt von foofile.tar.gz eingebettet ist. Ich glaube aber nicht, dass das unter Windows wirklich portabel ist, wegen des Popens.

import base64
import sys
import subprocess

inf = open(sys.argv[1],"r+b").read()
outs = base64.b64encode(inf)

decomppy = '''#!/usr/bin/python
import base64

def decomp(data):
    fname = "%s"
    outf = open(fname,"w+b")
    outf.write(base64.b64decode(data))
    outf.close()

    # You can put the rest of your code here.
    #Like this, to unzip an archive
    #import subprocess
    #subprocess.Popen("tar xzf " + fname, shell=True)
    #subprocess.Popen("rm " + fname, shell=True)
''' %(sys.argv[1])

taildata = '''uudata = """%s"""
decomp(uudata)
''' %(outs)

outpy = open("decomp.py","w+b")
outpy.write(decomppy)
outpy.write(taildata)
outpy.close()
subprocess.Popen("chmod +x decomp.py",shell=True)

0 Stimmen

+1 Ich glaube, dass dies ziemlich einfach auf die Windows-Plattform zu übertragen wäre. Nette Idee.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X