Ich habe einen Kontext-Manager, die Ausgabe in eine Zeichenfolge für einen Block von Code unter einem eingerückt erfasst with
Erklärung. Dieser Kontextmanager liefert ein benutzerdefiniertes Ergebnisobjekt, das nach Beendigung der Ausführung des Blocks die erfasste Ausgabe enthält.
from contextlib import contextmanager
@contextmanager
def capturing():
"Captures output within a 'with' block."
from cStringIO import StringIO
class result(object):
def __init__(self):
self._result = None
def __str__(self):
return self._result
try:
stringio = StringIO()
out, err, sys.stdout, sys.stderr = sys.stdout, sys.stderr, stringio, stringio
output = result()
yield output
finally:
output._result, sys.stdout, sys.stderr = stringio.getvalue(), out, err
stringio.close()
with capturing() as text:
print "foo bar baz",
print str(text) # prints "foo bar baz"
Ich kann natürlich nicht einfach eine Zeichenkette zurückgeben, weil Zeichenketten unveränderlich sind und somit die, die der Benutzer von der with
Anweisung kann nicht mehr geändert werden, nachdem ihr Codeblock ausgeführt wurde. Allerdings ist es etwas umständlich, das Ergebnisobjekt im Nachhinein explizit in eine Zeichenkette umzuwandeln mit str
(Ich habe auch damit gespielt, das Objekt aufrufbar zu machen, um die Syntax zu verbessern).
Ist es also möglich, das Ergebnis Instanz handeln wie eine Zeichenfolge, in der es in der Tat eine Zeichenfolge zurück, wenn benannt? Ich habe versucht zu implementieren __get__
aber das scheint nur bei Attributen zu funktionieren. Oder ist das, was ich tun möchte, nicht wirklich möglich?
0 Stimmen
Unabhängig davon, ob es eine Antwort auf diese Frage gibt oder nicht, würde ich es vorziehen, eine Klasse zurückzugeben, die
__str__
. Ich bin mir nicht sicher, inwiefern es ein Hindernis ist, dass man an einem bestimmten Punkt explizit sagen muss: "Genau hier ist der Punkt, an dem ich dies als String festhalte, keine weiteren Änderungen", indem manstr()
. Was ist also der Gewinn?0 Stimmen
@Mike: Hauptsächlich, dass ein Benutzer die Zeichenkette will, nicht ein Objekt, das in eine Zeichenkette umgewandelt werden muss.
0 Stimmen
Es sieht so aus, als ob UserString (naja, MutableString, aber das geht weg) im Grunde das ist, was ich will, also werde ich dafür stimmen, dies zu schließen. Bearbeiten: Hoppla, ich schätze, ich kann das nicht wirklich tun, da keiner der Gründe wirklich zutreffen.
2 Stimmen
@kindall: Dann schreibst du das in eine Antwort, markierst sie als richtig und machst weiter. Bonuspunkte für den Verweis auf die Seiten von UserString und MutableString auf docs.python.org.
0 Stimmen
"Hauptsächlich, dass ein Benutzer die Zeichenfolge wünscht". Na und? Was ist falsch daran, ihnen eine einfache alte Zeichenkette zu geben? Sie können sie auf die übliche Python-Art verketten:
string += string_data
. Was ist daran falsch?0 Stimmen
Sie können ihnen nicht einfach einen alten String in der
with
Anweisung, leider, denn die Daten, an denen sie interessiert sind (die Ausgabe, die innerhalb des Körpers derwith
Anweisung) ist nicht verfügbar, und die Zeichenkette kann nicht mehr geändert werden, nachdem Sie sie ihnen gegeben haben. Daher müssen Sie ein veränderbares Objekt zurückgeben, das eine Zeichenkette enthält, und die Zeichenkette in den Kontextmanager__exit__
(oder nach deryield
wenn Sie@contetmanager
).0 Stimmen
"und die Zeichenkette kann nicht mehr geändert werden, nachdem man sie ihnen gegeben hat. Das ist Standard-Python. Strings sind unveränderlich. Sie können eine neue Zeichenkette erstellen und ihr Daten hinzufügen. Welches Problem haben Sie eigentlich? Ich verstehe nicht, welches Problem Sie mit all dem zu lösen versuchen. Bitte erklären Sie, warum eine Zeichenkette ein Problem ist.
0 Stimmen
Ich versuche, einen Kontextmanager zu schreiben, der die Ausgabe dessen erfasst, was sich unter dem
with
Anweisung mit StringIO in eine Zeichenkette umwandeln. Ich möchte, dass der Benutzer dieses Kontextmanagers die Variable angeben kann, die die erfasste Ausgabe erhält imwith
Anweisung weil es dort hingehört. Aber an dem Punkt, an dem ich den Wert bereitstellen muss, landet er in der Benutzervariablen, ich weiß nicht tienen die erfasste Ausgabe noch nicht. Wenn ich ihnen eine Zeichenkette geben würde, wäre sie leer! Ich muss ihnen also etwas geben, das ich ändern kann, wenn ich die aufgezeichnete Ausgabe habe. Wenn ich das als Kontextmanager machen will, dann schon :-)1 Stimmen
Auschecken pypi.python.org/pypi/stringlike