niklasf / python-chess

A chess library for Python, with move generation and validation, PGN parsing and writing, Polyglot opening book reading, Gaviota tablebase probing, Syzygy tablebase probing, and UCI/XBoard engine communication
https://python-chess.readthedocs.io/en/latest/
GNU General Public License v3.0
2.44k stars 531 forks source link

RuntimeError when running engine with discord.py #396

Closed Starwort closed 5 years ago

Starwort commented 5 years ago

Bot initialised with

asyncio.set_event_loop_policy(EventLoopPolicy())
loop = asyncio.new_event_loop()

bot = Bot(loop=loop)

Error:

Traceback (most recent call last):
  File "/home/starwort/.local/lib/python3.6/site-packages/discord/ext/commands/core.py", line 63, in wrapped
    ret = await coro(*args, **kwargs)
  File "/home/starwort/ChessBot/cogs/chessboard.py", line 50, in start_game
    transport, engine = await chess.engine.popen_uci("/usr/games/stockfish")
  File "/home/starwort/.local/lib/python3.6/site-packages/chess/engine.py", line 2130, in popen_uci
    transport, protocol = yield from UciProtocol.popen(command, setpgrp=setpgrp, **popen_args)
  File "/home/starwort/.local/lib/python3.6/site-packages/chess/engine.py", line 803, in popen
    return (yield from loop.subprocess_exec(cls, *command, **popen_args))
  File "/usr/lib/python3.6/asyncio/base_events.py", line 1200, in subprocess_exec
    bufsize, **kwargs)
  File "/usr/lib/python3.6/asyncio/unix_events.py", line 203, in _make_subprocess_transport
    self._child_watcher_callback, transp)
  File "/usr/lib/python3.6/asyncio/unix_events.py", line 867, in add_child_handler
    "Cannot add child handler, "
RuntimeError: Cannot add child handler, the child watcher does not have a loop attached

Sysinfo: Ubuntu 18.04.1 LTS, Stockfish 8 64 at /usr/games/stockfish, python-chess 0.27.3, Python 3.6.7, GCC 8.2.0 Relevant code provided (probably). Can submit more if needed.

Starwort commented 5 years ago

N.B. I don't think the problem is discord.py because it does comply with the provided loop policy.

Starwort commented 5 years ago

Second note: printing type(loop) gets <class 'asyncio.unix_events._UnixSelectorEventLoop'>

niklasf commented 5 years ago

When manually creating an event loop, you need to do this:

asyncio.set_event_loop_policy(EventLoopPolicy())
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)  # <--

bot = Bot(loop=loop)

Or a shortcut:

asyncio.set_event_loop_policy(EventLoopPolicy())
loop = asyncio.get_event_loop()  # get, instead of new. initializes a new loop the first time

bot = Bot(loop=loop)
Starwort commented 5 years ago

Oh. Thanks, lol. I didn't know that. I'll try that now.

Update: Works perfectly! Thanks!