This post is essentially a duplicate of Can multiprocessing Process class be run from IDLE. I found it by searching SO for "[python-idle] multiprocessing". I give a revised and expanded version of my previous answer here.
As @Booboo said, an if __name __ == '__main__':
block is needed, at least on Windows and perhaps macOS. With that present, multiprocessing
itself runs fine when started from IDLE on Windows.
The failure is with printing. When multiprocessing
starts a new python process, it copies the current process sys.__stdout__
to both sys.__stdout__
and sys.stdout
in the new process. By default, print
writes the requested text to sys.stdout
.
When a GUI program is started from an icon or somehow other than a terminal, sys.__stdout__
and sys.stdout
are initialized to None
, at least on Windows. IDLE replaces sys.stdout
with an object whose write
method sends text to IDLE's Shell. It would be useless to copy the IDLE specific sys.stdout as it would not work.
If, instead you start IDLE from a command line with, on Windows, py -m idlelib
, the sys attributes are instead initialized to a normal python io object that sends text to the console/terminal. IDLE only replaces sys.stdout, so multiprocessing can copy the working sys.__stdout__
io
object to both sys attributes of the new process. By default, 'print' will then print to the console, as in this example.
import multiprocessing, sys
def pr():
print(sys.stdout)
if __name__ == '__main__':
p = multiprocessing.Process(target=pr)
p.start()
p.join()
# Writes the following to the
<_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>
Printing to CommandPrompt is obviously not great, but it is the best you can do with non-IDLE code. In your particular case, of wanting to animate tkinter objects (presumably on a tkinter canvas), you should use tk/tkinter after loops instead of multiprocessing. IDLE is designed for developing tkinter programs. Searching SO for [tkinter] animate
gives a few hundred hits.