I’m currently using multiprocessing so I can obtain user input while running other code. This version of code runs on ubuntu 19.04 for me, but for my friend it doesn’t work on windows.
import getch import time from multiprocessing import Process, Queue prev_user_input = ' ' user_input = ' ' # Getting input from the user queue = Queue(1) def get_input(): char = ' ' while char != 'x': char = getch.getch() queue.put(char) # Starting the process that gets user input proc = Process(target=get_input) proc.start() while True: # Getting the users last input while not queue.empty(): user_input = queue.get() # Only print user_input if it changes if prev_user_input != user_input: print(user_input) prev_user_input = user_input time.sleep(1/10)
How can I make this code work on windows?
Also the user input lags behind by one input. If the user presses a button it only prints after he pushes another button. Solutions on how to fix this would also help.
Edit 1: He’s using Python 3.7.4 and I’m using 3.7.3.
I tried this code as suggested
import msvcrt import time from multiprocessing import Process, Queue prev_user_input = ' ' user_input = ' ' # Getting input from the user queue = Queue(1) def get_input(): char = ' ' while char != 'x': char = msvcrt.getch() queue.put(char) # Starting the process that gets user input if __name__ == '__main__': proc = Process(target=get_input) proc.start() while True: # Getting the users last input while not queue.empty(): user_input = queue.get() # Only print user_input if it changes if prev_user_input != user_input: print(user_input) prev_user_input = user_input time.sleep(1/10)
But no characters were printed.
Edit 2:
I’m using msvcrt
module on windows and the getch
module on ubuntu. Sorry for not making that clear earlier in the post.
Advertisement
Answer
The following works for me on Windows. It incorporates all the changes I suggested in my comments under your question, including the final one about separate memory-spaces.
Something similar should also work under ubuntu using its version of getch()
, although I haven’t tested it. on The main process creates the Queue
and passes it as an argument to the get_input()
target function so they’re both using the same object to exchange data.
I also decode()
the bytes object returned from msvcrt.getch()
to convert it into a (1 character) Unicode UTF-8 string.
import msvcrt import time from multiprocessing import Process, Queue prev_user_input = ' ' user_input = ' ' def get_input(queue): char = ' ' while char != b'x': char = msvcrt.getch() queue.put(char.decode()) # Convert to utf-8 string. if __name__ == '__main__': # Getting input from the user. queue = Queue(1) # Starting the process that gets user input. proc = Process(target=get_input, args=(queue,)) proc.start() while True: # Getting the users last input while not queue.empty(): user_input = queue.get() # Only print user_input if it changes if prev_user_input != user_input: print(user_input) prev_user_input = user_input time.sleep(1/10)
Update
To hide the OS differences and make the code more portable, you could do the import
ing as shown below, which would also allow you to define the get_input()
function more like you did in the code in your question:
import os import time from multiprocessing import Process, Queue try: import msvcrt getch = msvcrt.getwch # Wide char variant of getch() that returns Unicode. except ModuleNotFoundError: # Not Windows OS - no msvcrt. from getch import getch prev_user_input = ' ' user_input = ' ' def get_input(queue): char = ' ' while char != 'x': char = getch() queue.put(char) if __name__ == '__main__': # For getting input from the user. queue = Queue(1) # Starting the process that gets user input. . . .