将asyncio与多人ProcessPoolExecutor结合

时间:2018-06-30 17:44:17

标签: python python-asyncio

是否可以采用诸如function sms_code_send($number='',$message='') { $username = 'username'; $password = '*******'; $originator = 'sender name'; $message = 'Welcom to ......, your activation code is : '.$message; //set POST variables $url = 'http://exmaple.com/bulksms/go?'; $fields = array( 'username' => urlencode($username), 'password' => urlencode($password), 'originator' => urlencode($originator), 'phone' => urlencode($number), 'msgtext' => urlencode($message) ); $fields_string = ''; //url-ify the data for the POST foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; } rtrim($fields_string,'&'); //open connection $ch = curl_init(); //set the url, number of POST vars, POST data curl_setopt($ch,CURLOPT_URL,$url); curl_setopt($ch,CURLOPT_POST,count($fields)); curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string); //execute post $result = curl_exec($ch); //close connection curl_close($ch); return $result; } 之类的阻塞功能,并使其在具有多个工作人员的class Team(models.Model): college = models.CharField(max_length=20) image = models.FileField(upload_to='documents/',null=True) def __str__(self): return self.college class Athletics(Match): time = ? player = models.ManyToManyField(Player, related_name='player') game_level = models.CharField(max_length=256, null=True, choices=LEVEL_CHOICES) # like semi-final, final etc game_specific = models.CharField(max_length=256,null=True, choices=EVENT_CHOICES) #like Men's Shot Put or Men's Triple Jump etc def __str__(self): return str(self.game_level) 中同时运行?

work

在具有4个以上内核的计算机上运行上述操作大约需要4秒钟。您将如何编写ProcessPoolExecutor以使上面的示例仅花费大约1秒的时间?

2 个答案:

答案 0 :(得分:6)

await loop.run_in_executor(executor, work)阻塞循环,直到work完成为止,结果您一次只能运行一个功能。

要同时运行作业,可以使用asyncio.as_completed

async def producer():
    tasks = [loop.run_in_executor(executor, work) for _ in range(num_jobs)]
    for f in asyncio.as_completed(tasks, loop=loop):
        results = await f
        await queue.put(results)

答案 1 :(得分:2)

问题出在producer中。它不等待作业在后台运行,而是等待每个作业完成,从而对其进行序列化。如果您将producer改写成这样(并保持consumer不变),则会得到预期的1s持续时间:

async def producer():
    for i in range(num_jobs):
        fut = loop.run_in_executor(executor, work)
        fut.add_done_callback(lambda f: queue.put_nowait(f.result()))