1

I am trying to multiprocess a large number of objects that I need to invoke a class function off. I cant pull the function outside of the class and so just need to figure out a way to speed up the calling of this function.

Many thanks in advance

import time
# - Bespoke Class that is standalone - #
class sub_class:
 def __init__(self, item_id, assumptions = "BlahBlahBlah"):
 self.item_id = item_id
 self.assumptions = assumptions
 self.test_count = 0
 def some_func(self, adder=1):
 self.test_count += adder
 time.sleep(0.1)
# - initialise a list of classes - #
item_ids = ['A', 'B', 'C', 'D']
items = [sub_class(_id) for _id in item_ids]
print( sum(_item.test_count for _item in items) )
# Prints out 0
# - invoke a class level function - #
[_item.some_func(adder=2) for _item in items]
print( sum(_item.test_count for _item in items) )
# Prints out 8
asked Feb 27, 2020 at 11:31
1

1 Answer 1

1

This works with only a minor change to some_func().

import time
from concurrent.futures import ProcessPoolExecutor, wait, ALL_COMPLETED
# - Bespoke Class that is standalone - #
class MyClass:
 def __init__(self, item_id, assumptions="BlahBlahBlah"):
 self.item_id = item_id
 self.assumptions = assumptions
 self.test_count = 0
 def some_func(self, adder=1):
 self.test_count += adder
 print(f"{self.item_id} executing some_func()")
 time.sleep(0.1)
 # note: we must return ourselves
 return self
# Don't omit this on Windows
if __name__ == '__main__':
 # - initialise a list of classes - #
 item_ids = ['A', 'B', 'C', 'D']
 items = [MyClass(item_id) for item_id in item_ids]
 print(sum(item.test_count for item in items))
 # Prints out 0
 # - invoke a class level function - #
 with ProcessPoolExecutor(max_workers=4) as executor:
 future_list = []
 for item in items:
 future_list.append(executor.submit(item.some_func, adder=2))
 wait(future_list, return_when=ALL_COMPLETED)
 # note: we must use the returned self to get the test count
 print(sum(future.result().test_count for future in future_list))
 # Prints out 8
 # note: the original items haven't changed
 print(sum(item.test_count for item in items))
 # Prints out 0

The "items" get copied to the new Process so you have to use the future return() values instead. Therefore, you can replace the original items using items = [future.result() for future in future_list] at some point after the wait().

answered Feb 27, 2020 at 13:20
Sign up to request clarification or add additional context in comments.

4 Comments

This works perfectly, exactly what I was looking for. ( Ive add a little progress bar and it work like a charm)
Perhaps, I shouldn't have been as hasty: how would you store the new outputs? e.g. Doing the below prints 0 tmp_list = [future.result().test_count for future in future_list] print(sum(tmp_list))
Are you sure? It prints 8 for me. See also my answer edit.
Apologies, this works; I had adapted a few things and left out the "return self" bit in MyClass.some_func (despite your comment not to forget it). thanks a lot

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.