Reputation: 2471
I am trying to execute python code through javascript directly:
In the javascript consolde, I type: IPython.notebook.kernel.execute("2+2")
But I get a strange output: "6CEA73CC644648DDA978FDD6A913E519"
Is there any way to take advantage of all the IPython javascript functions available, to run python code from the javascript console as depicted in the image? I'm sure there's a way but I've been beating at it for way too long and thought I would post here.
(I need this to build an app on top of IPython)
Thanks in advance!
Upvotes: 11
Views: 4711
Reputation: 1832
In an effort to isolate a minimum viable implementation, I was able to get responses back from the IPython kernel in just a couple of steps using essentially the same approach as ChrCury78.
Since I want to use the data returned from Python within Javascript, in these examples I just stored the message contents in a member on console
. (Unlike what ChrCury78 did, where he pushed the result to the output of the notebook cell.) In my real extension, I'll probably just attach it to a name on Jupyter
, or maybe an object of my own creation.
>> Jupyter.notebook.kernel.comm_manager.register_target("mycomm", (comm, msg) => {comm.on_msg( m => {console.retval = m.content.data})})
<- undefined
>> Jupyter.notebook.kernel.execute("from ipykernel.comm import Comm; Comm(target_name='mycomm').send('FOO')")
<- "{hex UID}"
>> console.retval
<- "FOO"
Multi-line Python code worked just fine, too; and, since I'd already imported Comm
, I didn't need to import it again:
>> Jupyter.notebook.kernel.execute("l = []\nfor x in range(5):\n l.append(x)\nComm(target_name='mycomm').send(l)")
<- "{hex UID}"
>> console.retval
<- Array(5) [ 0, 1, 2, 3, 4 ]
If you want to keep the kernel namespace unpolluted afterward, you could add a del Comm
to the end of the Python command.
I'll definitely be writing wrapper functions of some kind for both of these operations.
This is with Python 3.9.11 and the following packages installed:
ipykernel 6.9.2
ipython 8.1.1
ipython-genutils 0.2.0
ipywidgets 7.7.0
jupyter 1.0.0
jupyter-client 7.1.2
jupyter-console 6.4.3
jupyter-contrib-core 0.3.3
jupyter-contrib-nbextensions 0.5.1
jupyter-core 4.9.2
jupyter-highlight-selected-word 0.2.0
jupyter-latex-envs 1.4.6
jupyter-nbextensions-configurator 0.4.1
jupyterlab-pygments 0.1.2
jupyterlab-widgets 1.1.0
Upvotes: 0
Reputation: 437
After spending two days on it, here is the solution that worked for me.
To run Python code I am simpy using 'Jupyter.notebook.kernel.execute'. To get the answer from it I found usefull information at this link: https://jupyter-notebook.readthedocs.io/en/stable/comms.html
from ipykernel.comm import Comm
js_input = [] #case willing to track
def func_edit(cobj,text):
my_comm = Comm(target_name=cobj) #this is the callback
my_comm.send('' if text == '' else 'Return: ' + text)
global js_input
js_input.append(f'origin={cobj} text={text}')
from IPython.display import display, HTML
html = """
<script>
var comm_name = "this_control";
function fcalc(x)
{
// here I am passing to the Python function the value to edit and the address for getting the return value
IPython.notebook.kernel.execute("func_edit('" + comm_name + "','" + x.value + "')")
}
Jupyter.notebook.kernel.comm_manager.register_target(comm_name, function(comm, msg)
{
// comm is the frontend comm instance, msg is the comm_open message, which can carry data
// Register handlers for later messages:
comm.on_msg(function(msg) {
document.getElementById("out").value = msg.content.data;
});
//comm.on_close(function(msg) {...});
//comm.send({'foo': 40}); what is it??
});
</script>
<label for="in">Input:</label>
<input type="text" id="in" name="in" oninput="fcalc(this)">
<label for="out">Out:</label>
<input type="text" id="out">
"""
display(HTML(html))
Upvotes: 1
Reputation: 5287
You can call Python code execution from JavaScript with Jupyter.notebook.kernel.execute()
function.
Depend on this gist from Craig Dennis you can insert this code in Jupyter cell and run it
%%javascript
window.executePython = function(python) {
return new Promise((resolve, reject) => {
var callbacks = {
iopub: {
output: (data) => resolve(data.content.text.trim())
}
};
Jupyter.notebook.kernel.execute(`${python}`, callbacks);
});
}
function Log_out(r)
{ console.log(r); };
var code =
'for i in range(1,6):'+
' print( "#" + str(i))';
window.executePython( code )
.then(result => Log_out(result)); // Log out
Result would be output to browser javascript console.
Upvotes: 6
Reputation: 453
Are you aware of this blogpost? http://jakevdp.github.io/blog/2013/06/01/ipython-notebook-javascript-python-communication/
I think the exact way he uses doesn't work anymore, but maybe it can get you a step forward
Upvotes: 1