子类化 Future Class

Subclassing Future Class

我想子class Future class concurrent Python 模块。

文档:

The Future class encapsulates the asynchronous execution of a callable. Future instances are created by Executor.submit().

Executor 的文档没有解释 Future class 的来源。

...如何使 Executor.submit() 强制采用我的自定义 Future class?

为什么我需要它?

我喜欢 OOP,因为它创建了可读的代码。我希望结果如下所示:

for my_future in concurrent.futures.as_completed(...):
    my_future.my_custom_method()

Future 具体 class 的使用被硬连接到 Executor.submit()(无论是 processes or threads)。因此,我认为不可能完全按照您的要求去做。但是,您可以 return 传递给 Executor.submit() 的可调用结果的任何结果。因此,将您的自定义方法放在自定义 return class:

class my_result(object):
    def my_custom_method(self):
        pass

def x():
    return my_result()

with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
    futures = [executor.submit(x), executor.submit(x)]
    for my_future in concurrent.futures.as_completed(futures):
        my_future.result().my_custom_method()
               # ^^^^^^^^^

编辑 或者,如果您真的希望您的内部循环干净,请将最后两行更改为:

    for my_result in (f.result() for f in concurrent.futures.as_completed(futures)):
                   # ^^^^^^^^^^^^^^^^^^^^
        my_result.my_custom_method()

generator expression (f.result() ... (futures))as_completed 中获取期货的迭代器,并为您提供这些期货结果的迭代器。然后您可以遍历这些结果。

查看代码,ProcessPoolExecutor.submit() and ThreadPollExecutor.submit(), Excutor.submit() returns an instance of Future, which is defined in conccurent.futures._base.Future

所以,技巧来了。可以子类化替换原来的Future,然后在子类中添加自定义方法。

可行,但不推荐。为此,最好使用组合而不是继承。 Learn Python the Hard Way

中有一个很好的关于继承和组合的章节

回到问题,举个例子:

class Myclass(object):
    def __init__(self, workers=3):
         self.executor = concurrent.futures.ProcessPoolExcutor(workers)

    def run(self, job):
        '''Job to be run in a Executor'''

    def submit(self, jobs):
        self.futures = [executor.submit(self, foo, job) for job in jobs]

    def done(self, result):
        '''Dealing with the result'''

    def harvest(self):
        for my_future in concurrent.futures.as_completed(self.futures):
            self.done(my_future.result())

然后你可以继承 MyClass 并实现不同的 done 方法。