Open LottaMe opened 6 months ago
hint
To be able to do thehint
command, you need to be able to get an input from the user without it blocking the exercises from runnng.
Have a different thread running for the input then for exercise running.
Problems:
-> even more concurrency -> python gets weird with the main thread and it might lead to unexpected bugs that are also hard to test, when introducing more and more threads and processes.
Go beyond input statement, which blocks, and go with system level/lower level libraries to code a non-blocking input.
Problems:
-> handled differently on different operating systems -> tries to get lower level with python while still having a high level of abstraction will lead to unexpected bug
Have input() at the end of the exercise, after check_done. This does block it, but at this time the process is done and blocked anyway till it is restarted. If we put the input to only execute if check_done is false, this should not block the program.
Problems:
-> can we handle other commands like this? e.g. exit? -> NO INPUT IN SUBPROCESS
After trying out more there are more notes. I have experimented with threading, and while I was successful in getting hint command from the user, I have not managed to have it not block the program to continue. So that the user entering something was required.
I have managed to use pythons open(0) to access the standard input even in a child process and calling it in the exercise.run but it is also blocking the program similarly to threading. I guess terminating the process is not ending the open? But I would have to do more research on this.
with open(0) as stdin:
result = stdin.readline()
if "hint" in result:
print(hint_message)
A couple of ways to go from here:
Threading might not end up working, but I can’t say that for sure without more research. Maybe more interesting would be looking into asyncio, so that the input is asked for asynchronously, which as far as I know can be cancelled in the await. Currently I don’t know much about how this works, but from the little I’ve read it might be useful.
So from me trying to write or read about non blocking inputs in python I do not like the implementations I saw much. I think they are very unintuitive and would be difficult to understand when reading the code in the future or when someone else is reading the code.
This is a separately written code snippet that works for non blocking input. Something similar might be implemented somewhere in the code, possibly in combination with threading, multiprocessing, asyncio to complete this task.
import sys
import os
import fcntl
import time
fl = fcntl.fcntl(sys.stdin.fileno(), fcntl.F_GETFL)
fcntl.fcntl(sys.stdin.fileno(), fcntl.F_SETFL, fl | os.O_NONBLOCK)
input_received = False
while not input_received:
print("Waiting for user input")
try:
stdin = sys.stdin.read()
if stdin:
if "exit" in stdin:
input_received = True
except (IOError, TypeError):
pass
time.sleep(1)
Okay, I really don’t want to do this for reasons I will go into, but this would probably work, because processes can be terminated so easily. Basically after starting the exercise process, I could start an input process so the two of them are executed at the same time, hints can be printed and every time the exercise process is terminated or the exercise is done, the input process is terminated (if still running).
Now why do I not want to use this.
A lot of these solutions don’t really seem worth it for the feature it adds, especially because I could just add the hint as a comment In the file, so I will switch my focus to other things for now, and keep this issue and the comments for documentation in case I will revisit the task later.
Description
The user should be able to enter commands while running pylet to get a hint (hint) or exit the program (exit) (same as keyboardinterrupt)