2016-09-30 2 views
4

Ich versuche, die Korotinen in Python (und im Allgemeinen) zu verstehen. Ich habe über die Theorie, das Konzept und ein paar Beispiele gelesen, aber ich kämpfe immer noch. Ich verstehe das asynchrone Modell (habe ein bisschen Twisted gemacht), aber noch keine Coroutines.Wie ist das eine Coroutine?

One tutorial gibt dies als Koroutine Beispiel (ich ein paar Änderungen vorgenommen, mein Problem zu veranschaulichen):

async def download_coroutine(url, number): 
    """ 
    A coroutine to download the specified url 
    """ 
    request = urllib.request.urlopen(url) 
    filename = os.path.basename(url) 
    print("Downloading %s" % url) 

    with open(filename, 'wb') as file_handle: 
     while True: 
      print(number) # prints numbers to view progress 
      chunk = request.read(1024) 
      if not chunk: 
       print("Finished") 
       break 
      file_handle.write(chunk) 
    msg = 'Finished downloading {filename}'.format(filename=filename) 
    return msg 

Das mit diesem

ausgeführt wird
coroutines = [download_coroutine(url, number) for number, url in enumerate(urls)] 
completed, pending = await asyncio.wait(coroutines) 

am Generator Blick Koroutinen Beispiele kann ich siehe einige yield Aussagen. Hier gibt es nichts, und urllib ist synchron, AFAIK.

Da der Code asynchron sein soll, erwarte ich auch eine Reihe von verschachtelten Zahlen. (1, 4, 5, 1, 2, ..., "Fertig", ...). Was ich sehe, ist eine einzelne Zahl, die in einer Finished endet und dann eine andere (3, 3, 3, 3, ... "Fertig", 1, 1, 1, 1, ..., "Beendet"). ..).

An diesem Punkt bin ich versucht zu sagen, das Tutorial ist falsch, und das ist eine Coroutine, nur weil Async in Front hat.

+2

Ihre ist eine Co-Routine * nur *, weil Sie 'async def' verwendet haben. Es ist nicht sehr kooperativ, da es anderen Co-Routinen niemals nachgibt. Also ja, deine Analyse ist korrekt. –

+0

Ich habe einen Fehler gemacht, als ich das Tutorial ursprünglich geschrieben habe. Es wurde aktualisiert, um 'aiohttp' zu verwenden –

Antwort

12

Die co in Koroutine für kooperative steht. Das Ausgeben (zu anderen Routinen) macht eine Routine wirklich zu einer Co-Routine, weil nur durch Nachgeben beim Warten andere Co-Routinen verschachtelt werden können. In der neuen async Welt von Python 3.5 und höher, wird das normalerweise durch await-Ergebnisse aus anderen Korotinen erreicht.

Nach dieser Definition ist der Code nicht eine Coroutine. Soweit Python betroffen ist, ist es eine Coroutine Objekt, denn das ist der Typ für ein Funktionsobjekt mit async def erstellt.

Also ja, das Tutorial ist .. nicht hilfreich, in dem sie völlig synchronen, unkooperativen Code innerhalb einer Coroutine-Funktion verwendet.

Anstelle von urllib wäre eine asynchrone HTTP-Bibliothek erforderlich. Wie aiohttp:

import aiohttp 

async def download_coroutine(url): 
    """ 
    A coroutine to download the specified url 
    """ 
    filename = os.path.basename(url) 
    async with aiohttp.ClientSession() as session: 
     async with session.get(url) as resp: 
      with open(filename, 'wb') as fd: 
       while True: 
        chunk = await resp.content.read(1024) 
        if not chunk: 
         break 
        fd.write(chunk) 
    msg = 'Finished downloading {filename}'.format(filename=filename) 
    return msg 

Dieses Koroutine auf andere Routinen ergeben, wenn sie warten auf eine Verbindung hergestellt werden soll, und wenn für mehr Netzwerkdaten warten, als auch bei der wieder die Sitzung zu schließen.

Wir könnten weiterhin die Datei asynchron schreiben, aber das has portability issues; Die Bibliothek aiofiles project verwendet Threads zum Abladen der blockierenden Aufrufe an. Mit Hilfe dieser Bibliothek, würde der Code müssen aktualisiert werden, um:

import aiofiles 

async with aiofiles.open(filename, 'wb') as fd: 
    while True: 
     chunk = await resp.content.read(1024) 
     if not chunk: 
      break 
     await fd.write(chunk) 

Hinweis: der Blog-Post wurde aktualisiert, da wurden diese Probleme zu beheben.

+0

Ich bin ein langer Zeitpython2.7 Programmierer, aus irgendeinem Grund habe ich den neueren Python vermieden. Ich fand das Original-Tutorial und diese SO-Einträge sehr hilfreich. Ich bin verwirrt, dass diese Frage/Antwort nicht mehr Upvotes hat. Ist das Fachgebiet spezialisiert? Gute Arbeit! – Greg

+0

@Greg: Koroutinen sind eine relativ neue Ergänzung zu Python, also haben nicht viele mit ihnen gearbeitet. –

Verwandte Themen