2015-04-21 4 views
7

Ich arbeite an einer einfachen grafischen Netzwerkanwendung mit asyncio und tkinter. Ich stoße auf das Problem der Kombination der asyncio Ereignisschleife mit Tks Hauptschleife. Wenn möglich, würde ich es ohne Threads machen wollen, weil beide Bibliotheken (aber besonders tkinter) nicht sehr threadsicher sind. Derzeit bin ich Tk.update in einem asyncio Koroutine verwenden, die nur eine einzige Iteration der tk Ereignisschleife läuft:Ist es möglich, nur einen einzigen Schritt der asyncio Ereignisschleife auszuführen

@asyncio.coroutine 
def run_tk(tk, interval=0.1): 
    try: 
     while True: 
      tk.update() 
      yield from asyncio.sleep(interval) 
    except TclError as e: 
     if "application has been destroyed" not in e.args[0]: 
      raise 

jedoch im Interesse alle Möglichkeiten zu erforschen, ich frage mich, ob es möglich war, umgekehrt - wenn es möglich ist, nur eine einzige Iteration einer asyncio-Ereignisschleife innerhalb eines tk-Callbacks aufzurufen.

+0

können Sie [kombinieren, um die Hauptschleife Tk mit asyncio] (https://github.com/python/asyncio/issues/ 21), aber ich weiß nicht, ob das noch erlaubt, den Netzwerkverkehr zu verarbeiten (dh wie fließen Netzwerkereignisse in die Tk Hauptschleife)? –

+0

Es scheint, dass es funktionieren würde, aber es schummelt - Es erstellt einen TkEventLoop, der im Wesentlichen 'update' in einer Schleife ausführt, aber auch eine traditionelle Ereignisschleife erstellt, um Netzwerk-E/A auszuführen und in einem Thread auszuführen. Es ist das Schlimmste von beiden Welten; Der einzige Vorteil ist, dass direkte Rückrufe ('loop.call_later') direkt in der Tk-Ereignisschleife aufgerufen werden. – Lucretiel

+0

Ich vermisse ein minimales Arbeitsbeispiel in der Frage und in den Antworten. – buhtz

Antwort

9

Die fehlende öffentliche Methode wie loop.run_once() ist absichtlich. Nicht jede unterstützte Ereignisschleife verfügt über eine Methode zum Iterieren eines Schritts. Häufig zugrunde liegende API verfügt über Methoden zum Erstellen von Ereignisschleife und für immer ausführen, aber Emulation einzelner Schritt kann sehr ineffektiv sein.

Wenn Sie es wirklich brauchen können Sie einstufiges Iteration einfach implementieren:

import asyncio 


def run_once(loop): 
    loop.call_soon(loop.stop) 
    loop.run_forever() 


loop = asyncio.get_event_loop() 

for i in range(100): 
    print('Iteration', i) 
    run_once(loop) 
+0

warte ... was? Wie läuft 'run_forever' nur einmal? Wie macht das Sinn? – vitiral

+1

@cloudformdesign Siehe meine Antwort [hier] (http://Stackoverflow.com/a/29868627/2073595) für eine Erklärung. – dano

+0

und das war meine Frage! Vielen Dank! – vitiral

Verwandte Themen