Dynamisch erstellte Methode und Dekorateur, bekam die Fehlermeldung 'functools.teilweise' Objekt hat kein Attribut '__module__'
Ich bin derzeit mit EndpointsModel zum erstellen einer RESTful API für alle meine Modelle auf der AppEngine. Da ist es Erholsam, diese api haben eine Menge wiederholen Sie die code, die ich vermeiden möchte.
Beispiel:
class Reducer(EndpointsModel):
name = ndb.StringProperty(indexed=False)
@endpoints.api(
name="bigdata",
version="v1",
description="""The BigData API""",
allowed_client_ids=ALLOWED_CLIENT_IDS,
)
class BigDataApi(remote.Service):
@Reducer.method(
path="reducer",
http_method="POST",
name="reducer.insert",
user_required=True,
)
def ReducerInsert(self, obj):
pass
## and GET, POST, PUT, DELETE
## REPEATED for each model
Ich will, um Sie zu generisch. Also versuche ich die dynamische add-Methode der Klasse.
Was ich bisher versucht habe:
from functools import partial, wraps
def GenericInsert(self, obj, cls):
obj.owner = endpoints.get_current_user()
obj.put()
return obj
# Ignore GenericDelete, GenericGet, GenericUpdate ...
import types
from functools import partial
def register_rest_api(api_server, endpoint_cls):
name = endpoint_cls.__name__
# create list method
query_method = types.MethodType(
endpoint_cls.query_method(
query_fields=('limit', 'pageToken'),
path="%ss" % name,
http_method="GET",
name="%s.list" % name,
user_required=True
)(partial(GenericList, cls=endpoint_cls)))
setattr(api_server, "%sList", query_method)
# create insert method
# ...
register_rest_api(BigDataApi, Reducer)
Aber ich habe 'functools.partial' object has no attribute '__module__' exception.
Ich denke, es ist, weil es einige Konflikte zwischen endpoints.method
's Dekorateur und teilweise. Aber keine Ahnung, wie es zu vermeiden.
Traceback (most recent call last):
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/runtime/wsgi.py", line 239, in Handle
handler = _config_handle.add_wsgi_middleware(self._LoadHandler())
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/runtime/wsgi.py", line 298, in _LoadHandler
handler, path, err = LoadObject(self._handler)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/runtime/wsgi.py", line 84, in LoadObject
obj = __import__(path[0])
File "/Users/Sylvia/gcdc2013/apis.py", line 795, in <module>
register_rest_api(BigDataApi, Reducer)
File "/Users/Sylvia/gcdc2013/apis.py", line 788, in register_rest_api
)(partial(GenericList, cls=endpoint_cls)))
File "/Users/Sylvia/gcdc2013/endpoints_proto_datastore/ndb/model.py", line 1544, in RequestToQueryDecorator
@functools.wraps(api_method)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/functools.py", line 33, in update_wrapper
setattr(wrapper, attr, getattr(wrapped, attr))
AttributeError: 'functools.partial' object has no attribute '__module__'
Verwandte Artikel:
- - Klasse-Methode Unterschiede in Python: gebunden, ungebunden und statische
- Python - kann ich programmgesteuert dekorieren Klasse Methoden von einer Instanz der Klasse?
- Programmgesteuert generieren Methoden für eine Klasse
- Hinzufügen einer Methode zu einem Vorhandenen Objekt-Instanz
- Diese Frage könnte viel kürzer sein, indem Sie erklären, das Problem für nur
GenericInsert
zum Beispiel. - Ohne den Blick zu eng, es scheint, dass, wenn Sie Probleme mit Namenskonflikten dann
from functools import partial
->import functools
oder sogarfrom functools import partial as part
oder sowas funktionieren könnte. - Der Kern des Problems ist, dass functools.wraps (die Endpunkte code, aber nicht in einer Weise, die in irgendeiner Weise falsch oder ungewöhnlich) erwartet callable wird gewickelt, um eine __module__ attribute (unter anderem). Die Methode, die Sie vorbei es hat Sie nicht. bugs.python.org/issue3445 schlägt dies wurde als fix-Wert für python 3.3, aber nicht für die 2.7. So werden Sie wahrscheinlich nur brauchen, um die Dinge anders... nicht viel von einer Antwort, sorry.
- Danke, der link ist sehr hilfreich zu erklären, die Probleme
- Welche anderen Wege würden Sie vorschlagen, zu beheben Argumente für eine Funktion?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich auch gestolpert, ich war wirklich überrascht, für mich das Problem war, dass teilweise Objekte fehlen bestimmte Attribute, die speziell
__module__
und__name__
Sein, dass
wraps
standardmäßig verwendetfunctools.WRAPPER_ASSIGNMENTS
zum aktualisieren von Attributen, die standardmäßig auf('__module__', '__name__', '__doc__')
in python 2.7.6 trotzdem gibt es ein paar Wege, damit umzugehen ...Update nur Attribute ...
Wir uns hier einfach herauszufiltern, all das sind attribute, die nicht vorhanden ist.
Ein anderer Ansatz wäre, zu streng Angebot mit teilweise nur Objekte, Sie könnte klappen
wraps
mitsingledispatch
und erstellen gewickelt, teilweise Objekte, deren Attribute genommen werden würde von der tiefstenfunc
Attribut.Etwas entlang der Linien:
Diese ist etwas besser, weil jetzt können wir die ursprünglichen Funktionen docs, die vor vorgegeben, die eine teilweise Objekte doc string.
Diese können modifiziert werden, um nur suchen, wenn das aktuelle teilobjekt nicht bereits über die set-Attribut, das sollte etwas schneller beim Schachteln vielen teilobjekten ...
UPDATE
Scheint es, dass python(CPython) 3 (mindestens 3.4.3) nicht dieses Problem haben, da ich nicht weiß, noch sollte ich übernehmen alle Versionen von python 3 oder anderen Implementierungen wie Jython auch gemeinsam dieses Problem hier ist ein anderes Zukunft bereit Ansatz
ein paar Dinge zu beachten:
wraps
Funktion nur, wenn wir uns nicht wickeln teilweise, bei zukünftigen Versionen von python2 oder andere Versionen dieses Problem lösen.wraps
kopieren der Dokumente und andere Informationen, dieifilter
da es entfernt wurde, in Python ist3, ich habe timeit mit und ohneifilter
aber die Ergebnisse, wo nicht eindeutig, zumindest in python (CPython) 2.7.6, der Unterschied war marginal, am besten so oder so...In Python 3.5 habe ich festgestellt, dass ein Verweis auf die ursprüngliche Funktion wird beibehalten, die
partial
. Sie können es als.func
:Falls es der Fall, dass es durch ein Problem mit "Wickel" in functools, es gibt nichts hindert Sie schreiben Ihre eigenen teilweise nicht nennen-Packungen. Nach der python-Dokumentation, dies ist eine gültige Implementierung der partial:
Ich stolperte über dieses und dachte, dass wäre zu erwähnen mein workaround für dieses.
Wie richtig erwähnt von @samy-vilar Python ist3 nicht dieses Problem haben.
Ich habe einige code, der verwendet functools.wickeln und ausführen muss, um auf python2 sowie Python ist3.
Für python2 wir verwenden functools32 die Rückportierung von Python ist3 ' s functools für python2.
wraps
Durchführung dieses Paket funktioniert perfekt. Zusätzlich bietet lru_cache die nur in Python ist3 functools.In unserem Fall habe ich dies Problem gelöst, indem bilden von Unterklassen functools.teilweise:
NB Sie könnten auch Gebrauch machen von __getattr__ Umleitung Abfragen, aber ich dachte, das war eigentlich weniger gelesen (und macht es schwer irgendwelche nützlichen meta-Daten als mit __name__)
Eine ziemlich bequeme Lösung für python 2.7 ist hier beschrieben: http://louistiao.me/posts/adding-name-and-doc-attributes-to-functoolspartial-objects/
Nämlich:
Dieses Problem wird behoben, da der Python 2.7.11 (nicht sicher, welche spezifische Version es gefixt wurde). Sie tun kann
functools.wraps
auf einefunctools.partial
Objekt in 2.7.11.