0

I have a Python script with a simple function. I would like to run this function 2 times, simultaneously and was wondering if this was possible.

script.py:

from multiprocessing import Process
import time

def func1():
    time.sleep(1)
    print('Finished sleeping')


t1_start = time.perf_counter()
p1 = Process(target=func1())
p1 = Process(target=func1())

t1_stop = time.perf_counter()

print("elapsed time: {} sec".format(round(t1_stop - t1_start), 1))

Given output:

Finished sleeping
Finished sleeping
elapsed time: 2 sec

Expected output:

Finished sleeping
Finished sleeping
elapsed time: 1 sec

I have also tried this:

from multiprocessing import Process
import time

def func1():
    time.sleep(1)
    print('Finished sleeping')

if __name__ == '__main__':
    t1_start = time.perf_counter()
    p1 = Process(target=func1)  # note no ()
    p2 = Process(target=func1)  # note no ()

    p1.start()
    p2.start()

    t1_stop = time.perf_counter()

    print("elapsed time: {} sec".format(round(t1_stop - t1_start), 1))

However that gives this output:

elapsed time: 0 sec
Finished sleeping
Finished sleeping
3
  • Process(target=func1()) executes func1 immediately. Use Process(target=func1) instead. Note that you must start processes and should join them to see how long they run, by the way. Commented Oct 7, 2021 at 12:29
  • Please take a look at the mutliprocessing docs. Your system requires you to use an if __name__ == "__main__": guard for starting the processes. As the error says. Commented Oct 7, 2021 at 12:38
  • Re, "...simultaneously..." FYI, threads and processes do not, in and of themselves, provide guaranteed simultaneity. They provide concurrency, which is a weaker/broader concept. Concurrent tasks are allowed to happen at the same time, but not guaranteed to happen at the same time. If you ever write a program where it actually is important for A and B to happen simultaneously, then you probably will need to run it on a real-time operating system to provide that guarantee. Commented Oct 7, 2021 at 14:27

1 Answer 1

2
  • target=func1() calls func1 and passes its return value (in this case None) as the target argument for Process instead of passing the function func1 itself.

  • Process(...) just creates a Process object. You never really spawn/execute any of the created Process objects. You need to add a call to .start. Depending on the OS (ie if os.fork is used to spawn the new process), this will also require us to add __main__ guard (which is a best-practice anyway regardless of the used OS).

  • You are using p1 twice.

Try this:

from multiprocessing import Process
import time

def func1():
    time.sleep(1)
    print('Finished sleeping')

if __name__ == '__main__':
    t1_start = time.perf_counter()
    p1 = Process(target=func1)  # note no ()
    p2 = Process(target=func1)  # note no ()

    p1.start()
    p2.start()

    t1_stop = time.perf_counter()

    print("elapsed time: {} sec".format(round(t1_stop - t1_start), 1))

This gives the output

elapsed time: 0 sec
Finished sleepingFinished sleeping

which makes sense. If the function is executed 2 times in separated processes then the main process, the main process would not execute time.sleep(1) at all.

However, if we add .join() then the main process will be forced to wait for the child processes:

p1.start()
p2.start()

p1.join()
p2.join()

Now the output is the same as your required output:

Finished sleeping
Finished sleeping
elapsed time: 1 sec

EDIT: If you want an arbitrary number of processes with a loop:

...
times = 3
processes = []
for _ in range(times):
    p = Process(target=func1)
    p.start()
    processes.append(p)

for p in processes:
    p.join()
...
Sign up to request clarification or add additional context in comments.

11 Comments

I have updated the answer to include this... it does not work @DeepSpace
They also missed the __main__ guard.
@MisterMiyagi Works for me without __main__ guard
@DeepSpace That's system dependent. It fails with the spawn start method, which is the default on Windows and MacOS.
@MisterMiyagi Nice, didn't know about this. I'll add __main__ guard to the answer for future generations (it's a best practice anyway)
|

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.