I am new to the Python 3 multiprocessing
module and maybe seem to misunderstand one of its concepts. In my application I have the main thread, as usual, and another thread for some "background" work, called "BgThread". From that 2nd thread I spawn a Process
and run it via start()
.
The new subprocess now correctly starts and does its work. However, when I watch my application in the (VS Code) debugger, I can see that this subprocess also has this 2nd thread running, again called "BgThread".
Running on Linux I tried to spawn the thread via mp.set_start_method("spawn")
, as described in the multiprocessing docs, but with the same result. Moreover, when I set a breakpoint into the run()
method of my 2nd thread class, then in the subprocess it does NOT halt there (but it does so correctly in the main process).
Is this normal behaviour? If so, then I don't understand it - why does the subprocess also inherit this 2nd thread from its parent, even though it does not seem to really start it again via, as described above? Is there a need to prevent my subprocess to start that 2nd thread again?
CodePudding user response:
As @AndriiMaletskyi commented, what you are seeing must be some strange result introduced by your debugger. The following program run under Linux using spawn
to start new processes, first creates a thread and then starts a process. The thread is passed a multiprocessing.Value
instance that gets incremented 5 times in a loop in which it also prints out a message. If the subprocess inherited this thread, we would expect to see more than 5 messages printed out and the final value of this multiprocessing.Value
instance being greater than 5. Also, for good measure, the subprocess enumerates its threads and there is only one. If it had inherited the threads from the main process, there would have been at least two if not three.
from multiprocessing import Process, Value, set_start_method
from os import getpid
import threading
import time
def worker(*args):
first_time = True
for x, y in args:
time.sleep(1.1)
print(f'{x} {y} = {x y}')
if first_time:
first_time = False
for thread in threading.enumerate():
print('thread:', thread.name)
def my_thread(v):
for counter in range(1, 6):
print(f'time: {time.time()}, counter: {counter}, process id: {getpid()}, thread id: {threading.get_ident()}')
with v.get_lock():
v.value = 1
time.sleep(1)
if __name__ == '__main__':
set_start_method("spawn")
v = Value('i', 0, lock=True)
t = threading.Thread(target=my_thread, args=(v,))
t.start()
args = ((1, 2), (3, 4), (4, 5), (6,7))
p = Process(target=worker, args=args)
p.start()
p.join()
t.join()
print('Value =', v.value)
Prints:
time: 1637499015.9222672, counter: 1, process id: 33, thread id: 139689716135680
time: 1637499016.9244416, counter: 2, process id: 33, thread id: 139689716135680
1 2 = 3
thread: MainThread
time: 1637499017.925643, counter: 3, process id: 33, thread id: 139689716135680
3 4 = 7
time: 1637499018.926832, counter: 4, process id: 33, thread id: 139689716135680
4 5 = 9
time: 1637499019.9280066, counter: 5, process id: 33, thread id: 139689716135680
6 7 = 13
Value = 5