-
Notifications
You must be signed in to change notification settings - Fork 331
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gevent patch_all call in grequests breaks pymysql, etc. #8
Comments
I think I'm experiencing a similar issue - just used grequests for a django management command, and started seeing gevent threading errors in other, unrelated parts of the app. |
This breakage of other modules is what's still preventing me from using grequests. |
I am experiencing similar issues when i try to use grequests in a celery task. What do you think about Vitalys suggestion? |
The monkeypatching also breaks PyDev's debugger, which appears to use ordinary sockets. It would be much nicer if |
I'm leaning more and more towards recommending people use celery |
really? wouldn't that involve installing a message broker? Seems a little heavyweight.... surely there's an option to use gevent without hitting the nuclear patch all option? (i understand it's easy to criticise, if it's so easy why don't i just go ahead and write it, pull request gratefully accepted etc etc..) |
programming is hard? |
Sorry :) I agree that it's not ideal. |
ow. just took a look at the gevent api. agree it's far from straightforward! |
From a cursory glance, it looks like |
Could you use some kind of selective monkeypatch, where you only patch out the |
I find it really problematic for stability when an imported module all of a sudden changes so much of the environment for everything else that your app does. It's akin to having the rug pulled from under your feet :) |
It's intended to be used standalone. Anything with Gevent is. |
My app uses pymysql, PooledDB, Thrift client, Haigha AMQP library, etc., and it also needs a gevent-compatible HTTP client lib that doesn't mess up the app's environment. Presently, I'm working around this by running HTTP client from a separate posix thread, but I hate the unnecessary level of complexity and the extra kernel-level context switches that this entails. The app is I/O-bound, so it should be able to easily handle everything inside a single posix thread. @kennethreitz Regarding "It's intended to be used standalone. Anything with Gevent is.": the same functionality can be accomplished by monkey-patching the underlying requests module instead of monkey-patching the entire app's environment. Perhaps the requests module can formalize this by providing an API function that takes the necessary patch-points as args and applies them, and grequests would simply call that function during import. What do you think? |
+1 for idea of local monkey-patching
@kennethreitz |
Same question as @piotr-dobrogost |
In case it's helpful to others, I was importing grequests in some code which got used by many different processes. grequests was only actually used in one of the processes, but the import itself broke things (mod_wsgi+flask+threading in my case) as described above. My solution was to use a modified version of grequests.py that contains this at the top:
and in AsyncRequest's init method I call:
This will defer the monkey-patching until it's actually needed, which was enough to solve my problem. In my case I'm only actually using grequests in a very simple process with one thread that does nothing else, but I can imagine that this solution won't work in other more complex cases. |
Why is this still not fixed? Seems like lots of people cannot use grequests because it breaks lots of things. Is there any real need to monkey-patch anything beside sockets in requests module? |
A friendlier solution is for a module to use the appropriate geven objects directly instead of patching anything at all. requests could easily provide the necessary hooks for something like grequests to create gevent-compatible sockets, etc. directly. This way, gevent modules can coexist with legacy modules in the same app. |
@vitaly-krugl That should be fine too, though seems like it would require more extensive changes to requests. Has anyone taken a stab at forking / coding anything for this issue? P.S. Regarding @nonagonal 's solution, it did not work for me, since the application needs to run continuously and use sockets in multiple ways from multiple processes / tasks. Because of that the problem has been quite hard to detect in the first place... |
Just to add on: I've been using |
This library does what you're asking for: https://github.com/gwik/geventhttpclient. I thought I'd mention it as an alternative until this gets fixed. Also, if anyone's working on implementing this feature, you can take tips from that library. |
Check out my latest solution posted here #55 (comment), I wonder if it works for you guys or you could find any issues / point out any problems with what I've done there. @nonagonal: I see your solution uses |
I'm coming back on this issue, because gevent 1.1 introduced a warning message when monkey_patch is called multiple times:
I don't think libs should do monkey patch by themselves. If this is a requirement (and this is one obviously), I'd rather get a warning saying that "select", "socket", etc. should be monkey patched so that grequests can work. Sure, it's only a warning and it doesn't hurt much. But nobody likes useless warnings, and I'm getting this one at every unit test, every run and in my production logs. Please reconsider your decision to close this issue... |
I was looking forward to using this awesome package with my app and gevent until I noticed that it accomplishes gevent-compatibility via gevent.monkey.patch_all():
Unfortunately, patch_all() impacts all other packages/modules used by the app, breaking some of them that were not designed for reentrancy. For example, gevent.monkey.patch_all() broke the combination of pymysql/pooled_db (with sporadic, hard-to-reproduce failures); my app has several greenlets that on occasion make pymysql calls; I isolated the problem to gevent's monkey-patching of the socket module in that case.
A local solution involving monkey-patching of just the requests package to use gevent's variants of blocking API's would greatly enhance compatibility of grequests with apps and eliminate unexpected/undesirable side-effects on other packages. For example, I recently monkey-patched HBase/Thrift via the following code snippet with the desired effect on Thrift and no harm to the rest of the app (pymysql, etc.):
gevent-zeromq is another example of local monkey-patching, albeit a more complex one: https://github.com/traviscline/gevent-zeromq/blob/master/gevent_zeromq/__init__.py
Thank you,
Vitaly
The text was updated successfully, but these errors were encountered: