In the following program, when I append the process to a list (a seemingly pointless thing to do), it runs as expected. But if I remove the append, the processes destructor is called many times before it is even run. There are only n
constructions but (n)(n+1)/2
(where n
is the number of processes) destructions. This leads me to believe that each process is being copied into each new process and then immediately destroyed. Perhaps that is how the multiprocessing module works. It makes sense, since each process is a fork of the current one. But, what is the significance of appending to the list? Why does simply doing that stop this behaviour?
Here's the test and sample output:
import multiprocessing
class _ProcSTOP:
pass
class Proc(multiprocessing.Process):
def __init__(self, q, s):
s.i += 1
self._i = s.i
self._q = q
print('constructing:', s.i)
super().__init__()
def run(self):
dat = self._q.get()
while not dat is _ProcSTOP:
self._q.task_done()
dat = self._q.get()
self._q.task_done()
print('returning: ', self._i)
def __del__(self):
print('destroying: ', self._i)
if __name__ == '__main__':
q = multiprocessing.JoinableQueue()
s = multiprocessing.Manager().Namespace()
s.i = 0
pool = []
for i in range(4):
p = Proc(q, s)
p.start()
pool.append(p) # This is the line to comment
for i in range(10000):
q.put(i)
q.join()
for i in range(4):
q.put(_ProcSTOP)
q.join()
print('== complete')
Sample output with append:
constructing: 1
constructing: 2
constructing: 3
constructing: 4
returning: 3
returning: 2
== complete
returning: 1
returning: 4
destroying: 4
destroying: 3
destroying: 2
destroying: 1
Sample output without append:
constructing: 1
constructing: 2
constructing: 3
destroying: 1
constructing: 4
destroying: 1
destroying: 2
destroying: 3
destroying: 1
destroying: 2
returning: 1
returning: 4
returning: 2
== complete
returning: 3
destroying: 1
destroying: 3
destroying: 2
destroying: 4
One of the best practices to do what you want to do is by using + operator. The + operator creates a new list and leaves the original list unchanged.
Using . Inside square_root() , you create an empty list called result and start a for loop that iterates over the items in numbers . In each iteration, you use math. sqrt() to calculate the square root of the current number and then use . append() to add the result to result .
How to Start a Process in Python? To start a new process, or in other words, a new subprocess in Python, you need to use the Popen function call. It is possible to pass two parameters in the function call. The first parameter is the program you want to start, and the second is the file argument.
Adding the object to a list will prevent it from being deleted in child processes because after forking it will call "os._exit()" instead of clearing the whole stack
The relevant code is in multiprocessing/forking.py (constructor of Popen, which is called on "p.start()")
self.pid = os.fork()
if self.pid == 0:
if 'random' in sys.modules:
import random
random.seed()
code = process_obj._bootstrap()
sys.stdout.flush()
sys.stderr.flush()
os._exit(code)
Where _bootstrap setups the new process and calls "run" (code is in multiprocessing/process.py)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With