Get input in your Brython Graphics programs without the popup!
One aspect of running Brython in CodeHS that you might encounter is “blocking input.” Blocking input refers to input operations (like the input
function) that “block” the execution of the program until they receive an input. These are sometimes called “synchronous” functions, which means they need to happen immediately before the program can continue.
What’s more, output from previous lines cannot be written to the console until the blocking input
call is complete. The entire browser has to wait for the prompt to close, which means it’s unable to display any output.
The same goes for graphics output. Even if you use add()
to add a graphical object to the canvas, if there’s a call to input()
afterwards that input prompt will block the graphics from being drawn to the screen until it’s received the input.
More often than not, we want to ask the user to input something after printing something out or drawing something on the screen. The problem with blocking input is that it will block any output that is run before the input call. However there is another way to get user input in Brython without blocking (otherwise known as non-blocking input), using something called asynchronous functions. Asynchronous functions let you run your code in a special way so that the program knows when it needs to wait for something (like input) and when it doesn’t (like when you’re trying to output something before getting input). The asynchronous function async_input
will let you get input while also printing/drawing any output that comes before it. Additionally, the prompt will be shown in and the input will be collected from the console instead of popping up in its own dialog. The caveat to using asynchronous functions is that they require some special syntax and they need to be called in a special way.
To define an async function, you use the async
keyword before the def
keyword in the function definition. Async functions can only be called inside of other async functions, and they need to be called using the keyword await
. The one exception to this is the special function aio.run()
. By default Brython code is run synchronously, so aio.run()
is used to start running code asynchronously by calling an async function inside of it - in other words, aio.run()
is the entry point to asynchronous code. A good convention is to start writing your asynchronous code inside of an async function called main
and then run it with aio.run(main())
.
Even though you can only give aio.run()
1 function to run asynchronously, that doesn’t mean you have to put all of your asynchronous code in 1 function! You can still write multiple asynchronous functions and call them inside of other asynchronous functions, and you can also add parameters to your async functions (just make sure you pass them in when you call them). Additionally, you can still call synchronous functions inside of async functions, just not vice versa.
To recap, async functions let you ask users for input while still printing out/drawing any output that was run before to the screen. After learning a bit of syntax, you will be able to write cool, interactive programs like the Shape-o-matic below with ease!