I'm trying to write a Google-Appengine app that will fail nicely when datastore writes are disabled
Currently my main() looks like this:
def main():
make_datastore_readonly()
try:
run_wsgi_app(application)
except CapabilityDisabledError:
run_wsgi_app(NoWrite)
def main(): run_wsgi_app(application)
My app displays a traceback when the exception is raised.
def main(): run_wsgi_app(NoWrite)
It will properly show my error message (although for every request).
def make_datastore_readonly():
"""Throw ReadOnlyError on put and delete operations."""
def hook(service, call, request, response):
assert(service == 'datastore_v3')
if call in ('Put', 'Delete'):
raise CapabilityDisabledError('Datastore is in read-only mode') //Line 18
apiproxy_stub_map.apiproxy.GetPreCallHooks().Push('readonly_datastore', hook, 'datastore_v3')
Instead of getting my error message, I still get a traceback that looks like this:
Traceback (most recent call last): File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/webapp/_webapp25.py", line 703, in __call__ handler.post(*groups) File "/Users/kevin/Sche/main.py", line 232, in post me.put(); File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/db/__init__.py", line 1074, in put return datastore.Put(self._entity, **kwargs) File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/datastore.py", line 579, in Put return PutAsync(entities, **kwargs).get_result() File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/datastore.py", line 556, in PutAsync return _GetConnection().async_put(config, entities, local_extra_hook) File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/datastore/datastore_rpc.py", line 1553, in async_put return make_put_call(base_req, pbs, extra_hook) File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/datastore/datastore_rpc.py", line 1543, in make_put_call self.__put_hook, user_data) File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/datastore/datastore_rpc.py", line 1188, in make_rpc_call rpc.make_call(method, request, response, get_result_hook, user_data) File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/apiproxy_stub_map.py", line 519, in make_call self.__service, method, request, response, self.__rpc) File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/apiproxy_stub_map.py", line 207, in Call function(service, call, request, response) File "/Users/kevin/Sche/main.py", line 18, in hook raise CapabilityDisabledError('Datastore is in read-only mode') CapabilityDisabledError: Datastore is in read-only mode
So, my question is, why isn't the exception caught?
Edit:
This function is from this StackOverflow answer
def make_datastore_readonly(): """Throw ReadOnlyError on put and delete operations.""" def hook(service, call, request, response): assert(service == 'datastore_v3') if call in ('Put', 'Delete'): raise CapabilityDisabledError('Datastore is in read-only mode') //Line 18 apiproxy_stub_map.apiproxy.GetPreCallHooks().Push('readonly_datastore', hook, 'datastore_v3')
the main
function only register this application. Therefore, the exception will not raise in the main function. Therefore the try ... catch
statement won't work.
The way to handle this exception is defining a new RequestHandler. Then, all requests which want to have this feature should inherent from the new RequestHandler.
Class MyRequestHandler(RequestHandler):
def get(self):
try:
self.get_handler()
except CapabilityDisabledError:
pass
class MyRequest(MyRequestHandler):
def get_handler(self):
# ....
pass
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.