"Important: You SHOULD NOT attempt to override the run() method."

59 views
Skip to first unread message

kst...@lyft.com

unread,
Aug 31, 2016, 9:11:18 AM8/31/16
to gevent: coroutine-based Python network library
The doc at http://www.gevent.org/gevent.html has this emphatic message:

    Important: You SHOULD NOT attempt to override the run() method.

I want to create a Greenlet subclass that preserves the Flask context in a Flask application. I can write this code:

    class FlaskContextPropagatingGreenlet(Greenlet):
        def __init__(self, run=None, *args, **kwargs):
            if flask.request:
                run = flask.copy_current_request_context(run)
            super(FlaskContextPropagatingGreenlet, self).__init__(run, *args, **kwargs)

But this only works when subclasses pass run to __init__, e.g. using .spawn(). If a subclass overrides _run, it doesn't work.

It seems like the best solution here is to override/decorate the run method:

    class FlaskContextPropagatingGreenlet(Greenlet):
        def __init__(self, *args, **kwargs):
            if flask.request:
                self.run = flask.copy_current_request_context(self.run)
            super(FlaskContextPropagatingGreenlet, self).__init__(*args, **kwargs)

Is there anything wrong with this approach?

Thanks,
Kerrick

Jason Madden

unread,
Aug 31, 2016, 9:17:02 AM8/31/16
to gev...@googlegroups.com

> On Aug 30, 2016, at 21:41, kst...@lyft.com wrote:
>
> It seems like the best solution here is to override/decorate the run method:
>
> class FlaskContextPropagatingGreenlet(Greenlet):
> def __init__(self, *args, **kwargs):
> if flask.request:
> self.run = flask.copy_current_request_context(self.run)
> super(FlaskContextPropagatingGreenlet, self).__init__(*args, **kwargs)
>
> Is there anything wrong with this approach?

Other than being forbidden by the documentation, you mean? :)

gevent.Greenlet.run is tightly coupled to the lifecycle implementation of the greenlet. Certain APIs will not work before it is executed, and certain APIs will not work after it is executed. Which ones and the nature of the coupling is subject to change at any time. What you propose above will *probably* work, depending on the details, but it may break at any time.

Given that `_run` is the documented attribute in which to execute user code, it seems like something like this might handle both cases:

class AGreenlet(Greenlet):
def __init__(self, *args, **kwargs):
# Let it set up _run based on arguments
Greenlet.__init__(self, *args, **kwargs)
# Now we decorate it
self._run = decorate_run(self._run)
Reply all
Reply to author
Forward
0 new messages