Skip to content
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

Python raw_input #23

Closed
taybenlor opened this issue Jun 15, 2011 · 22 comments
Closed

Python raw_input #23

taybenlor opened this issue Jun 15, 2011 · 22 comments
Assignees

Comments

@taybenlor
Copy link

This isn't exactly an issue - more of a request.

I noticed the previous ticket in google code and I realise that there is probably no CommonJS way to do this, however I would love if it could be done.

I help out with http://ncss.edu.au (we teach python to high-school students) and we're looking for a way to get Python running in the browser so that students who don't have admin on their machine (ie at school computers etc) can write code and keep up with our challenge.

I'm not looking for someone to do all the work - I just need someone to point me in the direction of a solution. I see a few different possible ones:

  1. Dive into the compiled Python JS and work out some way to make raw_input work
  2. Hack at the emscripten compiler to see if there is a way to do it there

What do you think?

@taybenlor
Copy link
Author

Right now we're hacking apart python.js by doing this:

function BMb(c, e) {
  /* This is raw_input */
  var val = prompt("raw_input","");
  var arr = [];
  for(var i = 0; i < val.length; i++){
    arr.push(val.charCodeAt(i));
  }
  return FQ(u(arr, 0, t));
}
var RMb = Runtime.a(BMb, "_builtin_raw_input")

@ghost ghost assigned kripken Jun 18, 2011
@kripken
Copy link
Member

kripken commented Jun 18, 2011

I just committed most of the necessary code for this. I should be able to finish that and update the demo in the next few days.

@taybenlor
Copy link
Author

Thanks heaps :)

@amasad
Copy link

amasad commented Jun 19, 2011

Can this by any chance be asynchronous?
(i.e. block execution until the input is received by means of a callback)
Thanks.

@taybenlor
Copy link
Author

I can't see how that would work, the python internal expects c-style execution. With a prompt execution halts until the prompt has received input.

Perhaps as an alternative, to make it flexible, Emscripten could allow one to define ones own STDIN function? So it would do something like:

/* Emscripten default: */
emscripten = {
  stdin: function(){return prompt("?")}
}

/* Your code: */
emscripten.stdin = function(){return myInput.value}

@amasad
Copy link

amasad commented Jun 19, 2011

I understand this, but using the browser prompt is sub-optimal.
Maybe could be done in the user-space using the signal module?

@kripken
Copy link
Member

kripken commented Jun 19, 2011

It will be possible to easily change the stdin implementation, to replace window.prompt, so you can have it run a callback. However it will necessarily be synchronous because that is how CPython works, I don't see a way around that.

amasad, not sure what you mean by using the signal module here?

@amasad
Copy link

amasad commented Jun 19, 2011

I'm not really a Python programmer. But from what I know is that most VMs implement pause and resume methods, so I was looking for a way to possibly suspend/pause execution in Python VM until the user input is received and then to invoke resume() to continue execution.
The only thing I came around in my search is Python's signal.pause()

@kripken
Copy link
Member

kripken commented Jun 19, 2011

Calling window.prompt will pause execution, because it is synchronous. So it will behave exactly like raw_input in normal Python.

Likewise if you replace the stdin function, it will pause until your callback finishes.

@kripken
Copy link
Member

kripken commented Jun 19, 2011

Ok, pushed an update to the demo, please tell me if it works ok.

http://syntensity.com/static/python.html

The example code includes raw_input so just pressing execute should test it.

Will push an additional commit soon to allow modifying Module.stdin to customize the interactive input, I liked that idea (thanks!). Still waiting on automatic tests.

@amasad
Copy link

amasad commented Jun 19, 2011

I understand that window.prompt is blocking. But what if the input is to be received using a console like this one: http://amasad.github.com/jq-console/
It would be asynchronous, and the code would may look something like this:

emscripten.stdin(function (input_callback) {
   jqconsole.Input(input_callback);
});

jqconsole.Input will execute the passed callback argument when the input is received passing the inputted string.

Btw the demo is working great!

@kripken
Copy link
Member

kripken commented Jun 20, 2011

I see, so you would want to open a terminal like that, and wait for it to asynchronously return what the user enters? I don't know of a way to do that in JavaScript - basically need to wait synchronously for an asynchronous event. (With generators it might be done, perhaps, but they aren't widespread yet.(

In other news, final part of this issue is in f83a7e7. Marking as closed (just for the main issue, we can of course continue to discuss other stuff here).

@kripken kripken closed this as completed Jun 20, 2011
@taybenlor
Copy link
Author

I think using the Module.stdin style of hook it would be possible to use a terminal system like yours if combined with something like Web Workers. Or with some method of polling.

@max99x
Copy link
Contributor

max99x commented Jun 20, 2011

Unfortunately Web Workers do not support blocking (pausing, suspending) or even busy waiting (that locks the whole worker). I don't think it's possible to implement blocking on the Emscripten-level, but it might be doable in CPython specifically, if the CPython VM has a way to suspend and resume.

@amasad
Copy link

amasad commented Jun 20, 2011

I was trying to explore using signal.pause. The signal module did successfully load, however ran into the following error when tried calling the pause method:

JS crash: |ReferenceError: _pause is not defined|. Please let us know about this problem!

@taybenlor
Copy link
Author

I think it would be possible to combine a blocking while loop with a background worker to get the effect you want. In fact, it should be completely doable without a web worker. If a CPU can do it, JavaScript can. It just won't necessarily be very nice :P

@amasad
Copy link

amasad commented Jun 20, 2011

taybenlor, this would also mean blocking the browser's event loop which means blocking keydown/press events meaning we can't get the user input :S

@max99x
Copy link
Contributor

max99x commented Jun 20, 2011

Unfortunately JS uses a simple, blocking single-threaded event loop. A busy loop will hang your browser, regardless of whatever else may happen on the page (try it!). The same happens in a web worker. There's no way to toggle a mutex and leave the loop since nothing is allowed to run in the same JS context (thread) while you're inside a busy loop, and you can't access the worker context from another context; the busy loop will prevent the onmessage handler from running.

@taybenlor
Copy link
Author

Mmmm, you're right. I would still like to look into the Web Worker spec. It seems like it should be possible.

@taybenlor
Copy link
Author

Also, alternative direction to head with this is to make emscripten work based on deferred execution. So that you can essentially "pause" it, then resume it later.

@max99x
Copy link
Contributor

max99x commented Jun 20, 2011

That was my reaction as well. However, the spec has no mention of blocking or pausing a worker - you can only create, terminate and send messages. Something as simple as a processPendingEvents() API would have solved all of this.

@taybenlor
Copy link
Author

Perhaps @amasad should be using something more like http://bellard.org/jslinux/

tlively pushed a commit to tlively/emscripten that referenced this issue Mar 23, 2022
eagleoflqj pushed a commit to eagleoflqj/emscripten that referenced this issue Nov 16, 2024
Fix wrong condition in Instance::activate()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants