2017-04-05 20 views
14

TCP isteklerini ayrı bir sunucuya gönderen bir API sunucusu oluşturmak için aiohttp kullanıyorum. TCP isteklerini gönderen modül eşzamanlı ve amaçlarım için bir kara kutu. Yani benim sorunum, bu isteklerin tüm API'yi engellemesidir. Modül isteklerini, API'nın geri kalanını engellemeyen bir eşzamansız bir coroutine sarmak için bir yönteme ihtiyacım var.Senkronize bir işlevi bir async coroutine'de nasıl kaydederim?

async def sleep_async(delay): 
    # After calling sleep, loop should be released until sleep is done 
    yield sleep(delay) 
    return 'I slept asynchronously' 
+1

. Kooperatif çoklu görev ile istenen davranışa sahip olamazsınız, çünkü engellenmiş koroutin yalnızca istek bittikten sonra kontrol (verim) verir. –

+1

aiohttp http için iyidir. Http olmayan TCP için asyncio yeterlidir. – Udi

cevap

15

Sonunda bir cevap buldum: sadece basit bir örnek olarak sleep kullanarak Yani

, nasılsa engellenmeyen eşyordamın içinde zaman alıcı senkron kodu sarmak için herhangi bir yolu, böyle bir şey yoktur this thread. Aradığım yöntem run_in_executor. Bu, bir senkronizasyon işlevinin bir olay döngüsünü engellemeden eşzamansız olarak çalıştırılmasına olanak tanır. Yukarıdaki haberi sleep örnekte

, bu gibi görünebilir:

import asyncio 
from time import sleep 
from concurrent.futures import ProcessPoolExecutor 

async def sleep_async(loop, delay): 
    # Can set executor to None if a default has been set for loop 
    await loop.run_in_executor(ProcessPoolExecutor(), sleep, delay) 
    return 'I slept asynchronously' 

Ayrıca şu cevabı bakın -> How do we call a normal function where a coroutine is expected? Hep I/O engelle

+8

'ProcessPoolExecutor', yüksek bir paya sahiptir çünkü yeni bir python yorumlayıcısı başlatır. Birden çok işlemci kullanması gereken CPU yoğun bir göreviniz olduğunda kullanılır. Threading kullanan 'ThreadPoolExecutor' kullanmayı düşünün. – Oleg

+3

Ek bilgi için teşekkür ederiz. Özgün örnekte kullanılan işlem havuzu olmasına rağmen, 'ThreadPoolExecutor' biraz daha fazla araştırma yaptıktan sonra kullandım. Hala biraz jenky görünüyor, ama şimdiye kadar hepsi bir arada. –

+2

Sadece bir not, yeni bir yürütücü oluşturmak yerine, varsayılan yürütücüyü 'loop.run_in_executor (executor = None, func, * args)' diyerek kullanmak daha kolay olabilir (bkz. [Belgeler] (https: // docs. python.org/3/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.run_in_executor)). –

İlgili konular