Integrating multiprocessing.Process with concurrent.future._base.Future

时间:2017-12-18 08:20:01

标签: python python-3.x python-multiprocessing concurrent.futures

I have a requirement of creating child processes, receive results using Future and then kill some of them when required.

For this I have subclassed multiprocessing.Process class and return a Future object from the start() method.

The problem is that I am not able to receive the result in the cb() function as it never gets called.

Please help/suggest if this can be done in some other way or something I am missing in my current implementation?

Following is my current approach

FusedLocationProviderClient locationClient;


protected void startLocationUpdates() {


        // Create the location request to start receiving updates
        mLocationRequest = new LocationRequest();
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setInterval(UPDATE_INTERVAL);
        mLocationRequest.setFastestInterval(FASTEST_INTERVAL);

        // Create LocationSettingsRequest object using location request
        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
        builder.addLocationRequest(mLocationRequest);
        LocationSettingsRequest locationSettingsRequest = builder.build();

        // Check whether location settings are satisfied
        // https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient
        SettingsClient settingsClient = LocationServices.getSettingsClient(this);
        settingsClient.checkLocationSettings(locationSettingsRequest);

        // new Google API SDK v11 uses getFusedLocationProviderClient(this)
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            return;
        }

        locationClient = getFusedLocationProviderClient(this);getFusedLocationProviderClient(this).requestLocationUpdates(mLocationRequest, new LocationCallback() {
                    @Override
                    public void onLocationResult(LocationResult locationResult) {
                        // do work here
                        onLocationChanged(locationResult.getLastLocation());
                    }
                }, Looper.myLooper());
    }

1 个答案:

答案 0 :(得分:1)

在start方法中,您将创建一个新的Future,然后返回。这是一个与你设定结果的未来不同的未来,这个未来根本就没用过。尝试:

def start(self):
    run_thread = threading.Thread(target=self.run)
    run_thread.start()
    return self.f

然而,您的代码存在更多问题。您覆盖进程的start方法,将其替换为工作线程上的执行,因此实际上绕过了多处理。此外,您不应该导入_base模块,这是从前导下划线看到的实现细节。您应该导入concurrent.futures.Future(它是同一个类,但是通过公共API)。

这确实使用了多处理:

from multiprocessing import Process, Queue
from concurrent.futures import Future
import threading
from time import sleep


def foo(x,q):
    print('result {}'.format(x*x))
    result = x*x
    sleep(5)
    q.put(result)

class MyProcess(Process):

    def __init__(self, target, args):
        super().__init__()
        self.target = target
        self.args = args
        self.f = Future()

    def run(self):
        q = Queue()
        worker_thread = threading.Thread(target=self.target, args=(self.args+ (q,)))
        worker_thread.start()
        r = q.get(block=True)
        print('setting result {}'.format(r))
        self.f.set_result(result=r)
        print('done setting result')

def cb(future):
    print('received result in callback {}: {}'.format(future, future.result()))

def main():
    p1 = MyProcess(target=foo, args=(2,))
    p1.f.add_done_callback(fn=cb)
    p1.start()
    p1.join()
    sleep(10)

if __name__ == '__main__':
    main()
    print('Main thread dying')

现在你已经进入了一个新的过程,产生一个工作线程来执行你的目标函数不是真的必要,你可以直接执行你的目标函数。如果目标函数引发了一个你不会知道它的异常,那么只有在成功时才会调用你的回调。所以如果你解决了这个问题,那么你就离开了:

from multiprocessing import Process
from concurrent.futures import Future
import threading
from time import sleep


def foo(x):
    print('result {}'.format(x*x))
    result = x*x
    sleep(5)
    return result

class MyProcess(Process):

    def __init__(self, target, args):
        super().__init__()
        self.target = target
        self.args = args
        self.f = Future()

    def run(self):
        try:
            r = self.target(*self.args)
            print('setting result {}'.format(r))
            self.f.set_result(result=r)
            print('done setting result')
        except Exception as ex:
            self.f.set_exception(ex)

def cb(future):
    print('received result in callback {}: {}'.format(future, future.result()))

def main():
    p1 = MyProcess(target=foo, args=(2,))
    p1.f.add_done_callback(fn=cb)
    p1.start()
    p1.join()
    sleep(10)

if __name__ == '__main__':
    main()
    print('Main thread dying')

这基本上是ProcessPoolExecutor的作用。