asyncio-tkinter icon indicating copy to clipboard operation
asyncio-tkinter copied to clipboard

Running other async libs with asyncio-tkinter

Open duk3luk3 opened this issue 8 years ago • 1 comments

Hallo,

I just started this project: https://github.com/duk3luk3/faflauncher

Where I'm trying to use asyncio-tkinter and also aiohttp.

With the code as it is in the repo currently:

import tkinter as tk
from tkevents import TkEventLoop
import asyncio

import updater

class Application(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.pack()
        self.create_widgets()
        #asyncio.async(self.launch())
        #self.do_github()
        #asyncio.get_event_loop().run_until_complete(self.do_github())

    ...

    def launch(self, loop):
        f = asyncio.ensure_future(updater.fetch_tags('FAForever', 'client'), loop=loop)
        f.add_done_callback(app.set_github)

    def set_github(self, fut):
        tag, zipball_url = fut.result()

        self.label["text"] = "{} => {}".format(tag, zipball_url)

root = tk.Tk()
app = Application(master=root)
#app.mainloop()

loop = TkEventLoop(app)
app.launch(loop)
loop.mainloop()

I get this error:

Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib64/python3.6/tkinter/__init__.py", line 1699, in __call__
    return self.func(*args)
  File "/usr/lib64/python3.6/tkinter/__init__.py", line 745, in callit
    func(*args)
  File "src/tkevents.py", line 46, in <lambda>
    lambda cb, a : cb(*a),
  File "src/__main__.py", line 44, in set_github
    tag, zipball_url = fut.result()
  File "src/updater.py", line 20, in fetch_tags
    response = await fetch(session, url)
  File "src/updater.py", line 13, in fetch
    async with session.get(url) as response:
  File "/home/erlacher/git/faf/launcher/.venv/lib/python3.6/site-packages/aiohttp/client.py", line 603, in __aenter__
    self._resp = yield from self._coro
  File "/home/erlacher/git/faf/launcher/.venv/lib/python3.6/site-packages/aiohttp/client.py", line 231, in _request
    conn = yield from self._connector.connect(req)
  File "/home/erlacher/git/faf/launcher/.venv/lib/python3.6/site-packages/aiohttp/connector.py", line 378, in connect
    proto = yield from self._create_connection(req)
  File "/home/erlacher/git/faf/launcher/.venv/lib/python3.6/site-packages/aiohttp/connector.py", line 687, in _create_connection
    _, proto = yield from self._create_direct_connection(req)
  File "/home/erlacher/git/faf/launcher/.venv/lib/python3.6/site-packages/aiohttp/connector.py", line 698, in _create_direct_connection
    hosts = yield from self._resolve_host(req.url.raw_host, req.port)
  File "/home/erlacher/git/faf/launcher/.venv/lib/python3.6/site-packages/aiohttp/connector.py", line 669, in _resolve_host
    self._resolver.resolve(host, port, family=self._family)
  File "/home/erlacher/git/faf/launcher/.venv/lib/python3.6/site-packages/aiohttp/resolver.py", line 31, in resolve
    host, port, type=socket.SOCK_STREAM, family=family)
RuntimeError: Task <Task pending coro=<fetch_tags() running at src/updater.py:20> cb=[Application.set_github()]> got Future <Future pending cb=[_chain_future.<locals>._call_check_cancel() at /usr/lib64/python3.6/asyncio/futures.py:408]> attached to a different loop

This seems to be a somewhat common problem when trying to merge two async projects.

Can you give me any insights into why that is and how to fix it?

duk3luk3 avatar Aug 12 '17 08:08 duk3luk3

It looks to me, the problem is that the TkEventLoop does not install itself as “the” event loop until you call its mainloop() method. So when you instantiated your Application object prior to that, the call to ensure_future() is using the default asyncio.BaseEventLoop instance.

I think that any wrapper attempting to provide an asyncio-compatible API for a third-party event loop should provide something like an explicit install() method that you call up-front before doing any asyncio calls. This should install an event-loop policy to ensure that henceforth, all event loops are created by the wrapper.

This is what I did in glibcoro, for example.

ldo avatar Oct 14 '17 22:10 ldo