0

I'm so curious about this and need some advise about how can this happen? Yesterday I've tried to implement multiprocessing in Python script which is running on Spyder in Window PC. Here is the code I've first tried.

import multiprocessing
import time
start = time.perf_counter()
def do_something():
    print('Sleeping 1 second...')
    time.sleep(1)
    print('Done sleeping')
p1 = multiprocessing.Process(target=do_something)
p2 = multiprocessing.Process(target=do_something)
p1.start()
p2.start()
p1.join()
p2.join()
finish = time.perf_counter()
print(f'Finished in {round(finish-start,2)} second(s)')

It's return an error.

AttributeError: Can't get attribute 'do_something' on <module '__main__' (built-in)

Then I search for survival from this problem and also my boss. And found this suggestion

Python's multiprocessing doesn't work in Spyder IDE

So I've followed it and installed Pycharm and try to run the code on PyCharm and it's seem to be work I didn't get AttributeError, however I got this new one instead of

RuntimeError: 
        An attempt has been made to start a new process before the
        current process has finished its bootstrapping phase.

        This probably means that you are not using fork to start your
        child processes and you have forgotten to use the proper idiom
        in the main module:

            if __name__ == '__main__':
                freeze_support()
                ...

        The "freeze_support()" line can be omitted if the program
        is not going to be frozen to produce an executable. 

I've googled again then finally I got this

RuntimeError on windows trying python multiprocessing

what I have to do is adding this one line if __name__ == '__main__': before starting multiprocessing.

import multiprocessing
import time

start = time.perf_counter()

def do_something():
    print('Sleeping 1 second...')
    time.sleep(1)
    print('Done sleeping')
if __name__ == '__main__':    
    p1 = multiprocessing.Process(target=do_something)
    p2 = multiprocessing.Process(target=do_something)
    p1.start()
    p2.start()
    p1.join()
    p2.join()
finish = time.perf_counter()
print(f'Finished in {round(finish-start,2)} second(s)')

And it's work now moreover, it's not working only on PyCharm, now I can run this code on Spyder too. So that is why I have so curious? how come Spyder also work? This is quite persist because I'm also run this code on my other PC which is Window server 2016 with Spyder , I'm also do something.

Anyone can help explain what happen here why it's work?

Thank you.

PreuttiP
  • 39
  • 6

1 Answers1

1

There's a lot to unpack here, so I'll just give a brief overview. There's also some missing information like how you have spyder/pycharm configured, and what operating system you use, so I'll have to make some assumptions...

Based on the error messages you are probably using MacOS or Windows which means the default way python creates a child process is called spawn. This means it will start a completely new process from the python executable ("python.exe" on windows for example). It will then send a message to the new process telling it what function to execute (target), and optionally what arguments to call that function with. The new process will have to import the main file to have access to that function however, so if you are running the python interpreter in interactive mode, there is no "main" file to import, and you get the first error message: AttributeError.

The second error is also related to the importing of the "main" file. When you import a file, it basically just runs the file like any other python script. If you were to create a new child process during import that child would then also create a new child when it imports the same file. You would end up recursively creating infinite child processes until the computer crashed, so python disallows creating additional child processes during the import phase of a child process hence the RuntimeError.

Aaron
  • 10,133
  • 1
  • 24
  • 40
  • thank for your help explain. I'm using Window 10. Now I can see overall picture here. BTW, if I have other Window 10 PC with Spyder or Window server with Spyder, is there any way to make multiprocessing work with Spyder on these PC without install Pycharm? Thanks. – PreuttiP Jul 09 '21 at 03:57
  • 1
    @PreuttiP win 10 and server should be the same.. Spyder should be no different than pycharm, with the exception of a few things: Spyder by default uses IPython, which basically is an enhanced interactive mode that adds some convenience features. IPython unfortunately is sometimes inconsistent with forwarding `print` statements, and error messages back to the main interpreter in order for them to get printed out on the display. You can switch back to using a normal cmd prompt in spyder "run" settings to avoid this. – Aaron Jul 09 '21 at 15:56
  • 1
    Pycharm I have less experience with, but from what I hear, it's very eager to put everything in a virtual environment, which can make installing modules a little tricky. OTOH, it makes it easier to have python projects which use different specific versions of python or python libraries. I personally use Spyder, and any time I'm working with multiprocessing or graphical interfaces I switch to "Execute in an external system terminal" rather than the current console or a dedicated console (which are both IPython) – Aaron Jul 09 '21 at 15:58