0

I wrote this simple code in Python 3.11 to learn the multiprocessing module:

from multiprocessing import Process
import time

def proc(text):
    while True:
        print(text)
        time.sleep(1)

print(__name__)

if __name__ == '__main__':
    p = Process(target=proc, args=('hi',))
    p.start()

    input('Press any key to exit')
    p.terminate()

The idea is for process p to keep printing a text until the main process calls p.terminate().

But when I run this code, here's what I get:

print1

The process p is never called. But if I remove the line with the input() function, the program runs as expected:

print2

Why is this happening? How can I fix this? I'm running this code inside PyCharm IDE in Windows 10.

10
  • I cannot reproduce on Mac. I get what you expected. How exactly are your running this? It looks like you have VSCode. Why is __main__ and __mp_main__ being printed?? Commented Sep 17, 2023 at 4:24
  • 1
    Ok, but what does "run inside PyCharm" mean precisely? Please try to give us outputs that are consistent with your example, to avoid unnecessary confusion. To rule out it being a PyCharm issue, can you try just running outside of Pycharm, e.g. just from the console? Commented Sep 17, 2023 at 4:36
  • 1
    So, the "play button" in an IDE may involve all sorts of things to actually execute your file, which could potentially interfere with the multiprocessing.Process. This is why I ask. Even when I use PyCharm, atlhough I'm mostly on VSCode nowadays, I still just run the code from the terminal in PyCharm manually. Commented Sep 17, 2023 at 4:56
  • 1
    Hi @tdelaney! I tried to wrap the input('Press any key to exit') call inside the try/except as you suggested but the program didn't throw any exceptions. Also, I checked, and the input function is not returning righ away. It seems to be a problem in PyCharm's execution script or something like that. Even in online Python interpreters this code is working like expected. Commented Sep 17, 2023 at 16:24
  • 1
    @HenriqueRodrigues - thanks for the update. As juanpa.arrivillaga mentioned, IDE's can be tricky with code execution. It does leave me puzzled, though. Commented Sep 17, 2023 at 17:15

2 Answers 2

0

Any application that writes data to the standard out or standard error stream, or that takes data from the standard in stream, interacts with the terminal it is executing on.

Although that may sound complicated, it simply means that if your script uses print() or input(), how it behaves exactly from the point of view of the user will depend on the terminal the user is running it in. The terminal has to do the actual displaying of what is printed and it does the actual job of collecting user input. (Note that this gets more complicated if you use libraries that directly interact with system APIs reading keyboard input, like keyboard)

This terminal can be the Windows Console Host (the default for Command Prompt in early Windows 10 and before), the Windows Terminal (the default for PowerShell in Windows 11), but also a terminal emulator running your script on the cloud over SSH (running in some terminal emulation mode) for example, or whatever terminal your Linux distribution implements.

When you execute your script from an IDE, it can implement its own terminal that may work slightly differently from the terminal you're used to on your operating system. PyCharm is a good example. Its terminal behaves differently from both the Windows Terminal and the Windows Console Host, even though you may be running it on Windows.

A script that uses both terminal input and output and multiprocessing can cause additional confusion, if you're relying on the terminal responding in some timely fashion. Your script runs as expected on Windows Console Host and Windows Terminal, but doesn't on PyCharm's terminal.

In PyCharm, you can easily see this difference by running your script directly from the IDE with some run configuration. And then running it again from the 'Terminal' prompt with something like python myscript.py. You'll find that the behaviour in a system terminal is fine.

(Unrelated note: your input prompt says to press "any key", but input() will only terminate your script if someone presses Enter/Return, since that completes the collection of input by input())

You can't really 'fix' this, since there's nothing to fix - everything is working as it should. However, if the input() statement is only there for debugging purposes, a solution would be to use a library (like keyboard) that waits for user input without relying on the running Terminal. Install it with pip install keyboard or using the Project Settings in the UI, and then try this:

from multiprocessing import Process
import time
from keyboard import read_key


def proc(text):
    while True:
        print(text)
        time.sleep(1)


if __name__ == '__main__':
    p = Process(target=proc, args=('hi',))
    p.start()

    print("Press any key to stop the process...")
    read_key()
    p.terminate()

Note that this actually stops when you press any key, and works the same in all terminals.

Sign up to request clarification or add additional context in comments.

Comments

0

After a quick research I've found out what was the cause of the issue. The multiprocess.Process() has the functionality of the threading.Thread() library. This means that when you initiate the Process() object by using the target parameter in its initiator and passing a function/method, the Process() object will behave like a Thread() object.

Screenshot of python docs 1

Because of this, if you call p.terminate() you will kill the thread immediately after initiating it. Even if you remove p.terminate(), there is still another issue, even if Process() will have the functionality of a thread in this scenario, when you call p.start(), the process class is immediately shutting down the STDIN stream, thus not allowing you to use the input() method. Screenshot of python docs 2

https://docs.python.org/3.10/library/multiprocessing.html#multiprocessing.Process https://stackoverflow.com/a/5697326/16587692

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.