This is a base Python question. I am trying to decorate a @classmethod
with my own decorator, my_decorator
, which turns any function into a function which accepts a list of arguments to the original function as an argument. Here's an example.
You have a function foo()
and you if you wanted to run it, in sequence, on arguments, a
, b
, and c
. You would do
result_a = foo(a)
result_b = foo(b)
result_c = foo(c)
You could just make a function that works on a list of arguments, L=[a, b, c]
, and then you could do
results = foo_on_list([a, b, c])
I want to make a decorator that does exactly this for any function foo()
. What's more is that I want to use the multiprocessing
library to be able to execute foo(a)
asynchronously of foo(b)
. I wrote a nice decorator which works for static functions, but I am having trouble generalizing to functions which must either take a cls
or self
argument. Here is an example.
import multiprocessing as mp
def my_decorator(method):
def method_in_vector_form(obj, L, *args, **kwargs):
pool = mp.Pool(2)
print('Starting decorator')
results = [pool.apply_async(method, args=(obj, value)) for value in L]
pool.close()
pool.join()
return [r.get() for r in results]
return method_in_vector_form
class Foo(object):
@classmethod
def boo(cls, i):
print('Running from Foo\'s boo' + i)
@classmethod
@my_decorator
def bar(cls, chunk_id):
print('Running from Foo\'s bar')
cls.boo(chunk_id)
return chunk_id * 2
class Child(Foo):
@classmethod
def boo(cls, i):
print('Running from Child\'s version of boo' + i)
if __name__ == '__main__':
print(Foo.bar([1, 2, 3]))
print(Child.bar([1, 2, 3]))
I expect the following output (may be out of order because of asynchronicity).
Starting decorator
Running from Foo\'s bar
Running from Foo\'s boo 1
Running from Foo\'s bar
Running from Foo\'s boo 2
Running from Foo\'s bar
Running from Foo\'s boo 3
[2, 4, 6]
Starting decorator
Running from Foo\'s bar
Running from Child\'s version of boo 1
Running from Foo\'s bar
Running from Child\'s version of boo 2
Running from Foo\'s bar
Running from Child\'s version of boo 3
[2, 4, 6]
Here is the current output.
Starting decorator
Traceback (most recent call last):
File "C:\....\dec_example.py", line 36, in <module>
print(Foo.bar([1, 2, 3]))
File "C:\....\TextFromPdf\dec_example.py", line 10, in method_in_vector_form
return [r.get() for r in results]
File "C:\....\dec_example.py", line 10, in <listcomp>
return [r.get() for r in results]
File "C:\....\pool.py", line 599, in get
raise self._value
File "C:\....\pool.py", line 383, in _handle_tasks
put(task)
File "C:\....\connection.py", line 206, in send
self._send_bytes(ForkingPickler.dumps(obj))
File "C:\....\reduction.py", line 50, in dumps
cls(buf, protocol).dump(obj)
_pickle.PicklingError: Can't pickle <function Foo.bar at 0x0000000002897158>: attribute lookup bar on __main__ failed