Hallo,
ich bin neu bei Python, so bitte entschuldigt es, wenn meine Frage recht Anfängerhaft ist.
Grundsätzlich wollte ich fragen, ob und wie es möglich wäre, die Daten eines Decorators in der decorierten Methode verfügbar machnen kann. Wenn ich z.B. einen Pickle-Decorator hätte, mit dem ich vor dem Methodenaufruf die Daten lade und nach dem Methodenaufruf die Daten wieder zurückschreibe. Aber wie könnte ich auf die geladenen Daten zugreifen? So auf die Schnelle würde ich mir mit einer statischen Variable helfen. Doch jetzt wird es schwierig, wenn ich mehrere Threads habe z.B. eine cherrypy Anwendung, bei der ich die Daten in einem File speichere und sie für jeden Request neu lade und speichere (ob das jetzt aus Concurrency-Gründen Sinn macht sei jetzt dahingestellt, es soll ja nur als Beispiel dienen).
Gibt es etwa in Python eine Möglichkeit das elegant zu lösen, oder die Daten irgendwie wieder zurückgeben kann?
bye
Daten eines Decorators verfügbar machen
Hallo,
aus deiner Fragestellung wird nicht ganz deutlich, worauf deine Frage bezogen ist. Du würdest uns sehr helfen, wenn du ein kleines Codebeispiel postest. Allgemein zur Benutzung von Decoratoren, empfehle ich dir diesen Link.
EDIT: Gerade bemerkt, ist mein erster Beitrag hier...
aus deiner Fragestellung wird nicht ganz deutlich, worauf deine Frage bezogen ist. Du würdest uns sehr helfen, wenn du ein kleines Codebeispiel postest. Allgemein zur Benutzung von Decoratoren, empfehle ich dir diesen Link.
EDIT: Gerade bemerkt, ist mein erster Beitrag hier...
@EyDu: 15 Minuten, nachdem ich es gepostet hatte, kam mir auch schon die Idee . Code ist weiter unten. Was meint der Experte? Was mir noch missfällt ist das "*args, **kwargs" in der Definition von test_function...
@mjacob: Codebeispiel ist weiter unten
bye
@mjacob: Codebeispiel ist weiter unten
Code: Alles auswählen
#!/usr/bin/python
def pickle_decorator(f):
def call_function(*args, **kwargs):
pickle_data = "data read from pickled file"
result = f(*args, __pickle_data = pickle_data, **kwargs)
return result
return call_function
@pickle_decorator
def test_function(*args, **kwargs):
print "pickle:", kwargs["__pickle_data"]
test_function()
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Oder an den Dekorator. Hängt wohl ab wie man die Aufgabenstellung interpretiert.EyDu hat geschrieben:Einfach die Daten als Parameter an die dekorierte Funktion übergeben.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Warum nicht so (ungetestet)?
Code: Alles auswählen
def pickle_decorator(f):
def call_function(*args, **kwargs):
pickle_data = "data read from pickled file"
return f(pickle_data, *args, **kwargs)
return call_function
@pickle_decorator
def test_function(pickle_data):
print "pickle:", pickle_data
test_function()
„Lieber von den Richtigen kritisiert als von den Falschen gelobt werden.“
Gerhard Kocher
http://ms4py.org/
Gerhard Kocher
http://ms4py.org/
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Vielleicht ein persistentes memoizeDasIch hat geschrieben:Wieso nutzt man dafür überhaupt einen Dekorator. Das riecht arg nach sehr schlechtem Design hier.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
@ms4py: geht natürlich auch. Ich hatte nur die Defaultmethode von cherrypy im Hinterkopf, bei der die Position der Argumente auch noch einen Unterschied machen.
@DasIch: Für Verbesserungsvorschläge bin ich immer offen. Ursprünglich wollte ich den einzelnen Requestmethoden einer cherrypy-Anwendung ein SQLAlchemie-Sessionobjekt verfügbar machen (ähnlich wie Turbogears, doch leider hatte ich die Zeit und Muse noch nicht, mir den Code anzusehen). Die Idee wurde dann auf pickle und ähnliches ausgeweitet, das in bestimmten Methoden gemacht werden muss und immer den selben Code benötigt.
bye
@DasIch: Für Verbesserungsvorschläge bin ich immer offen. Ursprünglich wollte ich den einzelnen Requestmethoden einer cherrypy-Anwendung ein SQLAlchemie-Sessionobjekt verfügbar machen (ähnlich wie Turbogears, doch leider hatte ich die Zeit und Muse noch nicht, mir den Code anzusehen). Die Idee wurde dann auf pickle und ähnliches ausgeweitet, das in bestimmten Methoden gemacht werden muss und immer den selben Code benötigt.
bye
Dann nimm eine Klasse, dafür sind die da.regedit85 hat geschrieben:@DasIch: Für Verbesserungsvorschläge bin ich immer offen. Ursprünglich wollte ich den einzelnen Requestmethoden einer cherrypy-Anwendung ein SQLAlchemie-Sessionobjekt verfügbar machen (ähnlich wie Turbogears, doch leider hatte ich die Zeit und Muse noch nicht, mir den Code anzusehen). Die Idee wurde dann auf pickle und ähnliches ausgeweitet, das in bestimmten Methoden gemacht werden muss und immer den selben Code benötigt.
Code: Alles auswählen
class HasPickleData(object):
def __init__(self, file):
self.pickle_data = ...
class App(HasPickleData):
def index(self):
print self.pickle_data
Bei SQLAlchemy nutzt man dafür am besten eine globale scoped_session, dahinter versteckt sich ein Pool mit Datenbankverbindungen und du bekommst die jeweils lokale in deinem Kontext ob der ein Thread, Greenlet oder was auch immer ist.regedit85 hat geschrieben:@DasIch: Für Verbesserungsvorschläge bin ich immer offen. Ursprünglich wollte ich den einzelnen Requestmethoden einer cherrypy-Anwendung ein SQLAlchemie-Sessionobjekt verfügbar machen (ähnlich wie Turbogears, doch leider hatte ich die Zeit und Muse noch nicht, mir den Code anzusehen). Die Idee wurde dann auf pickle und ähnliches ausgeweitet, das in bestimmten Methoden gemacht werden muss und immer den selben Code benötigt.
Die Frage die sich mir momentan stellt ist wofür du genau pickle nutzt.
Danke für den Tipp, DasIch. Es würde also wie folgt aussehen:
Auf die Idee mit pickle bin ich nur gekommen, da ich mich derzeit in SQLAlchemy einlese, und noch nicht so weit bin damit das Objektmodel in die Datenbank zu bekommen. Da ich derzeit ja eine Zugriff habe (den meinen) sollte ich keine Probleme mit den Treads bekommen. Die Idee mit den Dekoratoren hatte ich, da der Code ja immer der selbe ist und immer gemacht werden muss, bevor (oder nachdem) man mit den Daten gearbeitet hat. So würde man z.B. auch nicht das Schliessen der Session vergessen.
bye
Code: Alles auswählen
# irgendwo global
Session = scoped_session(sessionmaker("sqlite://"))
# ...
# wenn ich dann eine session benötige
sess = Session()
sess.close()
bye
Dazu gibts doch auch den `ContextManager` mit `with`.
Code: Alles auswählen
class MyData(object):
def __init__():
self.conn = open_connection()
def __enter__():
return self.conn
def __exit__():
self.conn.close()
with MyData() as data:
process(data)
„Lieber von den Richtigen kritisiert als von den Falschen gelobt werden.“
Gerhard Kocher
http://ms4py.org/
Gerhard Kocher
http://ms4py.org/
Das geht viel eleganter mit contextlib.contextmanager
Code: Alles auswählen
from contextlib import contextmanager
@contextmanager
def db_connection():
connection = open_connection()
try:
yield connection
finally:
connection.close()
Ansichtssache Mir gefällt meine Lösung besserDasIch hat geschrieben:Das geht viel eleganter mit contextlib.contextmanager
„Lieber von den Richtigen kritisiert als von den Falschen gelobt werden.“
Gerhard Kocher
http://ms4py.org/
Gerhard Kocher
http://ms4py.org/