-
-
Notifications
You must be signed in to change notification settings - Fork 367
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
Issue #12786: Create hook for dispatching GUI messages asynchronously #589
base: main
Are you sure you want to change the base?
Conversation
575e5a9
to
b0b3613
Compare
b81f7e2
to
3194e85
Compare
Having some trouble reproducing the ubuntu 3.6 failure. I'm on a Macintosh, but I doubt it's OS specific. Any ideas what's going on there? Exact same requirements. Could it be flakey? |
3194e85
to
2f340e2
Compare
Hey @sonthonaxrk thank you for opening this. This issue has been dicussed a couple of times, but your approach is original, and may be interesting to discuss. This proposal would change the guarantee that shell messages are processed in order (even between comm messages), which may not be what we want. I think it is interesting to discuss how we could enable that usecase. |
Thanks for the review @SylvainCorlay. I've been running this code myself and I haven't found any glaring issues with it. From a very high level point of view, I think it's worthwhile discussing a design change of the protocol: to allow comms to be executed out of order (like what happens in this PR). I think this is really useful, and could open up some really cool possibilities with Jupyter. It's really incredible how many non-programmers use Jupyter now, and at a previous job I found myself implementing GUIs in Jupyter to ease their pain. I could absolutely see this becoming a pattern. Perhaps this could in the interim a hook, like in my first commit, where nothing is actually changed about how the basic kernel works. But users who really wanted this could do: class AsyncGIUKernel:
def should_dispatch_immediately(self, msg, *args):
try:
msg_type = msg['header']['msg_type']
if msg_type in self.comm_msg_types:
return True
except ValueError:
pass
return False That would at least make subclassing to do this easier. Another option could be to add an experimental flag, where a user could do the following (and it'd raise a warning for good measure: >>> from IPython import get_ipython
>>> get_ipython().kernel.set_async_comm = True
UserWarning: Async comms are an experimental feature, use at your own risk. From my perspective, I would be happy. |
FYI @jasongrout. |
2f340e2
to
0ab59fc
Compare
I have rebased the PR on top of master (which simplifies things a bit since there isn't a priority queue anymore). |
ae7637b
to
4d06758
Compare
Hey @SylvainCorlay, thanks for rebasing this. Does this mean we might be able to merge this in some form sometime soon? |
4d06758
to
290e761
Compare
@sonthonaxrk if we decide to get this in, it would be a good time, because the next ipykernel release will be a major one. However, I think this deserves a discussion with others familar with the protocol and widgets, like @minrk and @jasongrout. |
If it doesn't get in, I'll probably have to investigate using greenlet to achieve this (but that might be a bit of an esoteric solution to my problem). |
9f00ebb
to
9f5fbd5
Compare
This issue was discussed at the Jupyter widgets meeting yesterday, and @jasongrout has concerns about re-ordering messages. There was further discussion about using the same mechanism as the input request to make blocking calls to the front-end. cc @minrk - you might be interested in this. |
I remember we touched on that, but we couldn't quite think of the risk beyond it not being in the specification. And that's a completely valid concern IMO. However, I do think that some kind of mechanism for async controls might be a good thing. IPython is such a great platform for interactive computing, and it would be great if we could move on from some of the limitations that old UNIX style terminals usually have. Perhaps I should change the design of this PR. Instead of a boolean to change comms to be asynchronous, how about I create a new queue specifically for asynchronous messaging to the kernel. This would give us the notion of sync and async comms. The advantage of this is libraries would explicitly have to opt into the improved system. Perhaps the API for using the asynchronous queue could be as simple as this:
@SylvainCorlay @jasongrout @minrk Do you think that would be more amicable to the goals of the IPython project? :) |
If I'm reading this right it looks like the comm messages would be executed on the thread that is servicing the zmq socket? That seems worrying to me as if you get badly behaved callbacks you can lock up the zmq socket! Additionally, promoting all com traffic to running on a background thread also seems like it is going to cause chaos (I would bet a beverage of choice that there is someone out there with an ipywidget that has a callback that is doing something to a Qt window). Adding a second queue + thread for comm messages would solve the "lock zmq" problem, but not this problem. I suspect that there will either need to be a way for the user code to temorarily give up control back to the loop (I guess you could use |
This is actually what akernel is doing. |
9f5fbd5
to
872a1e8
Compare
I just rebased on master. # cell 1
from unfolded.map_sdk import UnfoldedMap
unfolded_map = UnfoldedMap(
mapUUID='ae4f5345-8507-49ec-85f6-a1f8c7bc2219'
)
unfolded_map
# cell 2
layers = await unfolded_map.get_layers()
# cell 3
layers
# shows [Layer(label='Point', id='25smxo6', is_visible=True)] Cell 2 doesn't hang, and cell 3 displays the right thing. However, in the notebook cell 2 appears as still executing (with |
872a1e8
to
96f43e7
Compare
I think this limitation is deeply buried inside ipykernel's architecture, and I don't see a way to work around it. |
96f43e7
to
ca2ae36
Compare
Oh, that's because of this commit: 22bd412 |
This fixes this issue I raised: ipython/ipython#12786
And allows you to use async and await on GUI events. Like
await button.click()
It's just experimental so far. But I haven't found any major issues yet. The only possible problem is where the output from Comm messages gets posted to. If you have a Comm.on_msg callback, that has a print statement, it will probably print to the last modified cell, and not the Cell which the comm was created in.
I don't think this will introduce any regressions.
I've split this into two commits, one introduces the hook. The other implements it. I'd personally be happy merging fist the first commit as it makes doing this in a subclass easier.
This changes the method signatures of the dispatch_shell and dispatch_control method. I hope that's okay.