Skip to content
Advertisement

How to rewrite this multiprocessing code for Windows?

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 importing 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.

    .
    .
    .
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement