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 input hook #2785
Comments
As a workaround until we solve this issue, this was (basically) bfroehle's suggestion: python -m gevent.monkey $(which ipython) Also, there's a pretty good explanation for why "gevent.monkey.patch_thread()" must occur before "import threading" at stackoverflow: |
Following up to my previous comment, is the input hook approach appropriate for applying gevent.monkey.patch_thread()? There are three specific points I noticed:
Maybe what we want, rather than |
For point 1., that doesn't seem like a big problem. gevent doesn't play nice with the rest of the world, so I think it is safe to assume that "once you go green, you never go...back" in a given process. For point 2, there's really nothing GUI about our integration with any eventloop. I don't know about point 3 in general, but I do know that the tornado + zmq eventloop we use in the kernel is fully compatible with gevent, as long as you do |
Hi minrk, Thanks for responding so quickly! So it seems the main problem remaining with daf's PR is that the gui/eventloop code (which does the gevent.monkey patching) should get executed before history is initiated. After a few hours familiarizing myself with the code, I think this means that init_gui_pylab() (which eventually calls inputhook.enable_gui) must get called before init_shell() (which eventually calls init_history) in these two apps' initialize method: frontend.terminal.ipapp.TerminalIPythonApp.initialize I'm going to try testing this out and then bring daf's code up to date with this additional change, but I have two questions about the zmq shell: Based on your previous comment that the kernel is compatible with gevent, do I need to concern myself with the order of init_history and init_gui_pylab in IPKernalApp.initialize? Also, why do kernel.zmq.eventloops and lib.inputhooks both exist separately? Is the kernel version the new way of doing things? Thanks again, Alex |
They are separate because the inputhook is only active when there is a terminal REPL involved (plain old IPython). The kernel (used by the notebook, qtconsole, etc.) handles things a bit differently. |
I seem to have rediscovered daf's stated problem. If you were to execute this code:
immediately after all imports in any one of the .py files in the frontend/terminal dir and then tried to run './ipython.py', the program raises the exception. This means that monkey patching must happen before certain IPython modules get loaded (obviously), and (perhaps less obviously) the --gui=gevent flag must be parsed and must load inputhookgevent.py before it loads parts (or arguably all) of the IPython core. At this point I'm not sure if it's worth it to proceed with this pr. As far as I understand, proceeding means we decide to add some special case in IPython loaders/code that parses the --gui flag and imports gevent before any threading imports, which is certainly a hack. Otherwise, we close the pr and tell the end-user to wrap calls to ipython using the above workaround. What do you think? |
it sounds like there is no sensible fix that really belongs in IPython. I guess gevent is just too disruptive for it to be anything other than the very first thing you do, so gevent compatibility would have to be a separately maintained entry point that wraps IPython before IPython is imported. |
Thanks for your time, minrk. To recap: the significant problem holding is back is gevent.monkey must be imported before threading. If that import order requirement suddenly did not matter anymore, we could certainly consider reviving and merging daf's work, but until then, we are stuck with a workaround. |
Yes @adgaudio: after reading this thread, I'm certainly -1 on putting anything in IPython that depends on a third-party's idea of how early in the life of sys.modules it must enter the import chain. The main issue is that something like that is bound to be brittle, and in that case it should be maintained by those who keep an eye on that library, not by us. Special-case hacks like that are sometimes unavoidable, but then I'd say that a wrapper entry point is the right solution. We deliberately keep the IPython top-level entry scripts short and simple precisely so that if anyone has to simply copy them to hack their startup process, they are literally only carrying one or two lines of code and it's not something likely to ever go significantly out of sync with IPython. |
Given this, I'm closing this one as the solution seems to be the entry point already indicated above. |
Why don't you make an ipython-gevent script, that would initialise gevent On 2 February 2013 21:19, Alex Gaudio notifications@github.com wrote:
|
@takluyver - Thanks for your suggestion. I emailed the IPython-dev list a couple days ago but haven't received any responses. If someone were to modify the IPython launcher, it could look like below. A fancier version I guess could use argparse and also launch ipcluster, etc. $ cat ~/.virtualenvs/t/bin/ipython #!/home/alexwork/.virtualenvs/t/bin/python # EASY-INSTALL-ENTRY-SCRIPT: 'ipython==0.13.1','console_scripts','ipython' __requires__ = 'ipython==0.13.1' import sys from pkg_resources import load_entry_point import gevent.monkey ; gevent.monkey.patch_all() sys.exit( load_entry_point('ipython==0.13.1', 'console_scripts', 'ipython')() ) |
Thanks @adgaudio. I saw your message on the mailing list, but I guess there hasn't been an immediate interest. That's probably expected - if lots of people were after ipython+gevent, the PR would have got more attention. Posting the launcher here so it's easy for other people to find is probably the best move. |
Hi folks! @adgaudio, cheers for taking this on - I had let it languish too much. I too agree that a specialized entry script will probably be ok. However, from what I had gathered in my initial work, isn't the "gui" eventloop necessary in order to prevent ipython blocking during readline (which is, typically, the majority of usage)? I think it would need to be both, and take out the parts for being able to do A couple more points raised in this discussion: @minrk, we might be behind in our zmq version, but that version lacked proper device support - the heartbeat used for connecting to a remote ipython kernel had to be patched out (was a simple fix in the end). I hope there is better support in mainline zmq now, and will advocate updating our project to use it. Also, I think there is a non-official way of "unmonkeypatching" - import the modules you know gevent touches ( |
That's correct, 13.0, which will be out in the next few weeks (RC1 here) should have green versions of everything. |
Hi all, I'm also interested in having gevent integration with the IPython shell. I read all the discussion both here and in the mailing list, and tried out a few of the suggestions. Yet I can't get it to work. My base case is the simple example that was sent to the mailing list a while back: # gtest.py
from gevent import spawn, wait
import time
def work():
while True:
time.sleep(2)
print "Hello" Then I have the following #!/usr/bin/env python
# EASY-INSTALL-ENTRY-SCRIPT: 'ipython==2.1.0','console_scripts','ipython'
__requires__ = 'ipython==2.1.0'
import sys
from pkg_resources import load_entry_point
import gevent.monkey ; gevent.monkey.patch_all()
sys.exit(
load_entry_point('ipython==2.1.0', 'console_scripts', 'ipython')()
) The background coroutine only runs when $ ./gpython.py
In [1]: from gtest import *
In [2]: spawn(work)
Out[2]: <Greenlet at 0x103152eb0: work>
In [3]: wait()
Hello
Hello
Hello I checked out the (very old) branch by @daf, and that works great. I have a project that uses the actor model for which gevent integration with the shell would be great. Is there still interest in having a separate executable that would allow this? Especially under the IPython notebook? What is the recommended approach? Thanks! |
Hi Berk, If you move the monkey patch line up so it gets called before import sys, your example works as you'd expect.
For the notebook (assuming recent ipython notebook version), you can just monkey patch in your notebook's first cell with
As far as I know (haven't been up to date much on this front), injecting a monkey patch before other imports is still the recommended way to use gevent + other libraries like IPython. |
Thanks @adgaudio for the reply! My expectation is that after I run |
Well your expectation that "Hello" prints after 2 seconds is correct, and it works for me (see below). You could try to use gevent.sleep and see if that works. If it does, you probably aren't monkey patching correctly. Also, I'm using anaconda ipython 2.1.0 and gevent 1.0.1 - not sure if that makes any difference. This is what appears on my screen when I run the example:
|
I still somehow can't get this behavior. Pretty frustrating, given that there are such few lines involved! I created the following repo, which also explains what I am typing: I still have to issue the Thanks, @adgaudio! |
Hi @adgaudio, I tried to retrace my steps for getting gevent integration, but it's not working on me. You seemed to suggest that it was working for you, is that correct? Thanks! |
@bbirand Your example does work for me, though I cannot use gipython.py to start an ipython shell because I use the anaconda distribution of python (which uses a different launcher). I'd guess that your problem is an issue with how your ipython or system packages are installed. I'd recommend trying anaconda, since it's free and they seem to solve most of these kinds of problems. |
Thanks again @adgaudio ,but it still is not working. I installed Anaconda, and made sure that I was running the right interpreter. I added an "Anaconda version" of my |
Is this loader still the recommended workaround? I get the following error with 2.3.0: #!/usr/bin/env python
# EASY-INSTALL-ENTRY-SCRIPT: 'ipython==2.1.0','console_scripts','ipython'
__requires__ = 'ipython==2.3.0'
import gevent.monkey ; gevent.monkey.patch_all()
import sys
from pkg_resources import load_entry_point
sys.exit(
load_entry_point('ipython==2.3.0', 'console_scripts', 'ipython')()
)
|
@ml31415 setuptools writes entrypoints that require a specific version. They have to be regenerated on every installation/update. If you want to hand-write an entrypoint, it should look something like this: #!/usr/bin/env python
import gevent.monkey
gevent.monkey.patch_all()
import IPython
IPython.start_ipython() |
Ah, that does the trick! Thank you! |
We would like to have integration with gevent through our inputhook. Work was begun on this, but stalled out with some design issues. Here is the original PR: #1654. This issue should be used for further discussing what needs to happen to get this feature done. When work continues, the original PR can be reopened or a new one created.
The text was updated successfully, but these errors were encountered: