сервер в потоке (Python3.9.0+aiohttp): RuntimeError: не удается зарегистрировать atexit после выключения

Этот фрагмент кода (минимальный сервер, работающий в потоке, код взят из здесь) отлично работает с Python3.8.3, но вызывает сообщение об ошибке с Python3.9.0:

import asyncio
import threading
from aiohttp import web


def aiohttp_server():
    def say_hello(request):
        return web.Response(text='Hello, world')

    app = web.Application()
    app.add_routes([web.get('/', say_hello)])
    runner = web.AppRunner(app)
    return runner


def run_server(runner):
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    loop.run_until_complete(runner.setup())
    site = web.TCPSite(runner, 'localhost', 8080)
    loop.run_until_complete(site.start())
    loop.run_forever()


t = threading.Thread(target=run_server, args=(aiohttp_server(),))
t.start()

Сообщение об ошибке:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python3.9/threading.py", line 954, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.9/threading.py", line 892, in run
    self._target(*self._args, **self._kwargs)
  File "/home/alkhinoos/nikw/nikw/z2.py", line 21, in run_server
    loop.run_until_complete(site.start())
  File "/usr/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
    return future.result()
  File "/usr/lib/python3.9/site-packages/aiohttp/web_runner.py", line 121, in start
    self._server = await loop.create_server(
  File "/usr/lib/python3.9/asyncio/base_events.py", line 1460, in create_server
    infos = await tasks.gather(*fs, loop=self)
  File "/usr/lib/python3.9/asyncio/base_events.py", line 1400, in _create_server_getaddrinfo
    infos = await self._ensure_resolved((host, port), family=family,
  File "/usr/lib/python3.9/asyncio/base_events.py", line 1396, in _ensure_resolved
    return await loop.getaddrinfo(host, port, family=family, type=type,
  File "/usr/lib/python3.9/asyncio/base_events.py", line 856, in getaddrinfo
    return await self.run_in_executor(
  File "/usr/lib/python3.9/asyncio/base_events.py", line 809, in run_in_executor
    executor = concurrent.futures.ThreadPoolExecutor(
  File "/usr/lib/python3.9/concurrent/futures/__init__.py", line 49, in __getattr__
    from .thread import ThreadPoolExecutor as te
  File "/usr/lib/python3.9/concurrent/futures/thread.py", line 37, in <module>
    threading._register_atexit(_python_exit)
  File "/usr/lib/python3.9/threading.py", line 1374, in _register_atexit
    raise RuntimeError("can't register atexit after shutdown")
RuntimeError: can't register atexit after shutdown

В чем дело ? Та же проблема возникает с Python 3.9.1. Решена ли эта проблема с Python 3.9.2? Возможно, здесь есть относительная проблема.


person suizokukan    schedule 27.12.2020    source источник
comment
@JasonPan это именно то, что было не так с моим кодом, большое спасибо за помощь.   -  person Shivam Sahil    schedule 29.06.2021
comment
@ShivamSahil С удовольствием. Я опубликую комментарий как ответ.   -  person Jason Pan    schedule 30.06.2021
comment
Проголосовали! :)   -  person Shivam Sahil    schedule 30.06.2021


Ответы (2)


Не знаю, что вы сделали, но я использовал 127.0.0.1 вместо localhost, и ошибка устранена!

person Anwar Husain    schedule 29.03.2021

Как указано в руководстве по Python — Объекты потока

Другие потоки могут вызывать метод join() потока. Это блокирует вызывающий поток до тех пор, пока поток, чей метод join() вызывается, не будет завершен.

После вызова t.start() в основном потоке основной поток завершится. Затем процесс завершается.

Если вы хотите запускать дочерний поток вечно или до тех пор, пока он не завершится, вы должны вызвать t.join() в основном потоке после t.start().

person Jason Pan    schedule 30.06.2021