2015-12-17 20 views
16

Python 3.5 kodunda bir Python 3.5 async for deyimini dönüştürmenin bir yolu var mı?`async 3.4

PEP 0492async for

async for TARGET in ITER: 
    BLOCK 
else: 
    BLOCK2 

iter = (ITER) 
iter = await type(iter).__aiter__(iter) 
running = True 
while running: 
    try: 
     TARGET = await type(iter).__anext__(iter) 
    except StopAsyncIteration: 
     running = False 
    else: 
     BLOCK 
else: 
    BLOCK2 

eşdeğerdir ancak Python __aiter__ var olmadığını söyler 3.4

+2

çalışan bir Python 3.5 kod, daha sonra kaynağında bakmak varsa '.__ aiter __()' ve '.__ ANEXT __()' yöntemleri (farklı ITER için farklı olabilir). OldBunny2800 @ – jfs

+0

Bunu aradığınız inanıyoruz https://stackoverflow.com/questions/30191556/coroutine-in-python-between-3-4-and-3-5-how-can-i-keep-backwords- uyumluluk –

cevap

7

Hayır, yok, async/await (__aiter__, vs yanı python 3.5'de tanıtıldı. (Sadece async for olarak, sıralı olan) (eğer paralel/kerede tüm görevleri çalıştırmak ve hepsi bitene kadar bekleyebilir varsa) veya asyncio.Queue içine sonuçları bastırıyor py3.4 üzerinde yakın şey asyncio.gather olduğunu. Düzenleme: soruda açıklandığı gibi async for alternatifinin son örneğine bakın. İşte

asyncio.gather için piton docs ala bir örnektir:

import asyncio 

@asyncio.coroutine 
def task(id): 
    print("task: {}".format(id)) 
    yield from asyncio.sleep(random.uniform(1, 3)) 
    return id 

tasks = [ 
    task("A"), 
    task("B"), 
    task("C") 
] 
loop = asyncio.get_event_loop() 
results = loop.run_until_complete(asyncio.gather(*tasks)) 
loop.close() 
print(results) 

Çıktı:

import asyncio 

@asyncio.coroutine 
def produce(queue, n): 
    for x in range(n): 
     print('producing {}/{}'.format(x, n)) 
     # todo: do something more useful than sleeping :) 
     yield from asyncio.sleep(random.random()) 
     yield from queue.put(str(x)) 


@asyncio.coroutine 
def consume(queue): 
    while True: 
     item = yield from queue.get() 
     print('consuming {}...'.format(item)) 
     # todo: do something more useful than sleeping :) 
     yield from asyncio.sleep(random.random()) 
     queue.task_done() 


@asyncio.coroutine 
def run(n): 
    queue = asyncio.Queue() 
    # schedule the consumer 
    consumer = asyncio.ensure_future(consume(queue)) 
    # run the producer and wait for completion 
    yield from produce(queue, n) 
    # wait until the consumer has processed all items 
    yield from queue.join() 
    # the consumer is still awaiting for an item, cancel it 
    consumer.cancel() 


loop = asyncio.get_event_loop() 
loop.run_until_complete(run(10)) 
loop.close() 

Düzenleme:: async for İşte

task: B 
task: A 
task: C 
['A', 'B', 'C'] 

asyncio.Queue için biridir soruda açıklandığı gibi alternatif:

Bu yapıldığında, bir koruyucu sonuç hem __aiter__ ve __anext__ çıkarılması ve do_something yöntem kendi içinde bir durdurma özel durum veya dönüş basitleştirilebilir 10 ila
import asyncio 
import random 

class StopAsyncIteration(Exception): 
    """""" 

class MyCounter: 
    def __init__(self, count): 
     self.count = count 

    def __aiter__(self): 
     return self 

    @asyncio.coroutine 
    def __anext__(self): 
     if not self.count: 
      raise StopAsyncIteration 

     return (yield from self.do_something()) 

    @asyncio.coroutine 
    def do_something(self): 
     yield from asyncio.sleep(random.uniform(0, 1)) 
     self.count -= 1 
     return self.count 

@asyncio.coroutine 
def getNumbers(): 
    i = MyCounter(10).__aiter__() 
    while True: 
     try: 
      row = yield from i.__anext__() 
     except StopAsyncIteration: 
      break 
     else: 
      print(row) 

loop = asyncio.get_event_loop() 
loop.run_until_complete(getNumbers()) 
loop.close() 

numarası (genellikle geçersiz değeri: None, "", -1, vs.)

+0

Eşzamansız bir işlev yinelenen bir işlev döndürürse, onu bir değişkene atayabilir ve üzerinde yineleme yapmak için standart bir iç döngü kullanabilir miydiniz? (: Liste, kayıt düzeni dict, set, vb yani), sonra emin, daha sonra yineleme yapabilirsiniz Eğer 'sonuç gibi bir şey varsa – OldBunny2800

+0

Evet = somecoro()' ve 'somecoro' bir iterable döndürür bekliyor. Buradaki soru, async yineleyici üzerinde yineleme yapmaktı. Örneğin, bir grup HTTP isteğini bir araya getirip, bunların tamamlanmasını beklemek zorunda kalmadan, her birinin içeriğini, mümkün olan en kısa sürede getiriyordu. – nitely

+1

"asyncio.gather" ve "asyncio.Queue" için bazı örnekler ekledim. Elbette, eğer py3.5 üzerindeyseniz, bir async yineleyici bir sıradan daha iyi (daha basit/okunabilir) olduğu gibi, en azından çoğu durumda düşünebilirim. – nitely