2015-01-23 24 views
7

Tümü sırayla karşıdan yüklemek için hardcoded bir sayfa listesiyle yinelenen bir download_all işlevine sahibim. Ancak, bir sayfanın sonuçlarını temel alarak listeye dinamik olarak eklemek isterseniz, bunu nasıl yapabilirim? Örneğin, ilk sayfayı indirin, ayrıştırın ve sonuçlara göre diğerlerini etkinlik döngüsüne ekleyin.Python asyncio's olay döngüsünün ne yapması gerektiğini dinamik olarak ekleyin

@asyncio.coroutine 
def download_all(): 
    first_page = 1 
    last_page = 100 
    download_list = [download(page_number) for page_number in range(first_page, last_page)] 
    gen = asyncio.wait(download_list) 
    return gen 

if __name__ == '__main__': 
    loop = asyncio.get_event_loop() 
    futures = loop.run_until_complete(download_all()) 

cevap

1

Lütfen Web Crawler example'a bir bakın.

URL'leri getirme görevleri için saklamak üzere asyncio.JoinableQueue kuyruğunu kullanır, ancak birçok yararlı tekniği de gösterir.

+2

Eğer bu bir referans burada ve daha sonra gerçek bir örnek verdi olsaydı daha güzel olurdu. – KronoS

+0

Örnek, normal SO'lardan daha büyük. Buraya itilmeye değer olduğundan şüpheliyim. –

2

Bunu gerçekleştirmenin bir yolu bir Kuyruk kullanmaktır. işin "birimleri" başlangıçta asyncio olay döngü verilir görevler/vadeli ayrıdır sağlayabilirsiniz sizin asyncio bir kuyruğu kullanarak

#!/usr/bin/python3 

import asyncio 

try: 
    # python 3.4 
    from asyncio import JoinableQueue as Queue 
except: 
    # python 3.5 
    from asyncio import Queue 

@asyncio.coroutine 
def do_work(task_name, work_queue): 
    while not work_queue.empty(): 
     queue_item = work_queue.get_nowait() 

     # simulate condition where task is added dynamically 
     if queue_item % 2 != 0: 
      work_queue.put_nowait(2) 
      print('Added additional item to queue') 

     print('{0} got item: {1}'.format(task_name, queue_item)) 
     yield from asyncio.sleep(queue_item) 
     print('{0} finished processing item: {1}'.format(task_name, queue_item)) 

if __name__ == '__main__': 

    queue = Queue() 

    # Load initial jobs into queue 
    [queue.put_nowait(x) for x in range(1, 6)] 

    # use 3 workers to consume tasks 
    taskers = [ 
     do_work('task1', queue), 
     do_work('task2', queue), 
     do_work('task3', queue) 
    ] 

    loop = asyncio.get_event_loop() 
    loop.run_until_complete(asyncio.wait(taskers)) 
    loop.close() 

. Temel olarak bu, bazı koşullara bağlı olarak ekstra "birimler" in eklenmesine izin verir.

Yukarıdaki örnekte numaralandırılmış görevlerin bile terminal olduğunu unutmayın, bu durumda ek bir görev eklenmez. Bu sonuçta tüm görevlerin tamamlanmasıyla sonuçlanır, ancak sizin durumunuzda başka bir öğenin kuyruğa eklenip eklenmeyeceğini belirlemek için kolayca başka bir koşul kullanabilirsiniz.

Çıktı:

Added additional item to queue 
task2 got item: 1 
task1 got item: 2 
Added additional item to queue 
task3 got item: 3 
task2 finished processing item: 1 
task2 got item: 4 
task1 finished processing item: 2 
Added additional item to queue 
task1 got item: 5 
task3 finished processing item: 3 
task3 got item: 2 
task3 finished processing item: 2 
task3 got item: 2 
task2 finished processing item: 4 
task2 got item: 2 
task1 finished processing item: 5 
task3 finished processing item: 2 
task2 finished processing item: 2 
+0

Bu durumda, 'asyncio.Queue' kullanılmasına gerek yoktur, çünkü siz bu arada kullanmıyorsunuz. Sıradan 'liste' şunları yapacak: https://gist.github.com/452f9a9f385e1d839309f76bb421ae3c – azag0