jupyter-c-kernel
jupyter-c-kernel copied to clipboard
Allow to read from stdin
So it is possible to use functions like scanf
.
Thanks to @ryukinix for letting me know about this enhancement.
Could you give an example of scanf
? I get an unassigned value. It's a great project, much appreciated. If possible it would be useful to have a more extensive example notebook.
Unfortunately that is not implemented yet, @sdd3. Input functions doesn't works yet. The proposal is a behavior for input functions like the default python kernel related behavior, communicating with the jupyter frontend. Like this:
Ah, ok. I misunderstood the first post in this thread. Thanks for clearing that up. Any idea when an input function might be incorporated?
I'm trying to implement this, but I'm a little stuck:
My idea is to override all fgets
calls with my_fgets
using a macro. This my_fgets
in master.c
notifies its parent (subprocess.Popen in kernel.py
) somehow to send an input_request
through stdin_socket
. When input_reply
is received from the frontend the data is piped to the stdin of subprocess.
I managed to request and receive input from the frontend as such, which works just fine:
def _raw_input(self, prompt, ident, parent):
# Flush output before making the request.
sys.stderr.flush()
sys.stdout.flush()
# Send the input request.
content = dict(prompt=prompt)
msg = self.session.send(self.stdin_socket, u'input_request', content, parent, ident=ident)
# Await a response.
ident,reply = self.session.recv(self.stdin_socket, 0)
try:
value = reply['content']['value']
except:
self.log.error("Got bad raw_input reply: %s"%Message(parent))
value = ''
return value
def execute_request(self, stream, ident, parent):
''' Wrap execture_request function to force input call '''
value = self._raw_input('Some info:', ident, parent)
self.log.warn('Value: {}'.format(value))
super(CKernel, self).execute_request(stream, ident, parent)
Questions
I cannot find or decide on a mechanism to notify from master.c
to Python subprocess
instance that input is requested:
- Is there anybody with an opinion or a better suggestion than:
- Using
zmq
sockets directly from master.c? - Introducing new messaging system between master.c and kernel.py?
- Piping some predefined message through stderr/stdout?
- Using
- I looked into raising signals
SIGTTIN
andSIGTTOU
(good blog), but they appear to be used from parent-to-child and I want from child to parent.
Ok I'm 1 step further, (for at least a POSIX solution, sorry windows guys :stuck_out_tongue: ).
From master.c
I raise SIGTTIN
to the parent process as such, and in contrary to the name kill
the c process will continue just fine.
kill(getppid(), SIGTTIN);
I have chosen SIGTTIN
because people might want to use SIGUSR1
and SIGUSR2
in notebooks.
From within kernel.py
I can catch this as such:
def sig_forwarder(a,b):
self.log.warn('Caught SIGTTIN from C')
signal.signal(signal.SIGTTIN, sig_forwarder)
p = self.create_jupyter_subprocess([self.master_path, binary_file.name])
while p.poll() is None:
p.write_contents()
p.write_contents()
signal.signal(signal.SIGTTIN, signal.SIG_DFL)
Is there any alternative for reading inputs using scanf?
I chose fgets
to be safe in the implementation I am/was working on.
For reference see: https://stackoverflow.com/a/3302594
Sent from my OnePlus ONEPLUS A5000 using FastHub
It can be done as following:
#include<stdio.h>
#include<string.h>
int max2i(int x, int y);
char *input_string="25,67"; //<-----input value
int main()
{
int a,b,c;
printf("input 2 integer numbers:");
sscanf(input_string, "%d,%d", &a, &b); //<------use sscanf instead of scanf
c=max2i(a,b);
printf("max value of (%d,%d) is %d\n", a,b,c);
return 0;
}
int max2i(int x,int y)
{
if(x>y)
return x;
else
return y;
}
The @masterfish2015 solution didn't work for me with Jupyter 4.4.0 and Notebook 5.5.0, neither from Firefox or Chrome.
A fork of this project but realize the input from the tab
Just like this
I am happy that I have found a version that can use the scanf and it works fine in jupyter notebook 6.1.5 .
Alse, I have found a repo from a university that can help us using comment to replace the real input.
Here is the repo
That's pretty cool workaround!
Cordialmente, Manoel Vilela.
Em sáb., 12 de ago. de 2023 00:16, つき 滝猫 @.***> escreveu:
The cool thing is, just print the <inputRequest> before trying to input any thing
For example:
int x;printf("<inputRequest"); //It will prompt for a dialogue helping user to get the inputscanf("%d", &x);printf("%d", x);
— Reply to this email directly, view it on GitHub https://github.com/brendan-rius/jupyter-c-kernel/issues/3#issuecomment-1675650848, or unsubscribe https://github.com/notifications/unsubscribe-auth/AB2J57T6RJMP6WNQ7A6T47TXU3YSVANCNFSM4CBJHSIQ . You are receiving this because you were mentioned.Message ID: @.***>
That's pretty cool workaround! Cordialmente, Manoel Vilela. Em sáb., 12 de ago. de 2023 00:16, つき 滝猫 @.> escreveu: … The cool thing is, just print the <inputRequest> before trying to input any thing For example: int x;printf("<inputRequest"); //It will prompt for a dialogue helping user to get the inputscanf("%d", &x);printf("%d", x); — Reply to this email directly, view it on GitHub <#3 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AB2J57T6RJMP6WNQ7A6T47TXU3YSVANCNFSM4CBJHSIQ . You are receiving this because you were mentioned.Message ID: @.>
Ah, this was my comment. I had removed because of this problem:
Once you use the <inputRequest>
, you'll also know that the HTML tag is unstable, and it can be redefined by the Jupyter developers. Also, it method leaks the input stream. It is very dangerous when you deployed Jupyter Hub for your campus/lab/enterprise. (Recommendation from IBM)
To solve this, write a header file and force #include
it into the source .cpp
file. But its security effects are considered.
You can see my C++ header file in my C++ kernel for Jupyter
project:
https://github.com/takinekotfs/jupyter-cpp-kernel/blob/master/jupyter-cpp-kernel/resources/gcpph.hpp