Как запустить веб-приложение aiohttp во вторичном потоке - PullRequest
0 голосов
/ 31 марта 2020

Следующий код взят из aiohttp документов https://docs.aiohttp.org/en/stable/ работает:

from aiohttp import web

async def handle(request):
    name = request.match_info.get('name', "Anonymous")
    text = "Hello, " + name
    return web.Response(text=text)

app = web.Application()
app.add_routes([web.get('/', handle),
                web.get('/{name}', handle)])

if __name__ == '__main__':
  web.run_app(app)

enter image description here

Но перехват основного веб-сервера основным потоком недопустим: веб-сервер должен находиться в отдельном неосновном потоке и подчиняться главному внутреннему приложению.

Я не могу определить, как запустить Веб-приложение на вторичном потоке. Вот что я попробовал:

  1. Невозможно запустить фрагмент кода в ipython repl:

Я пытался запустить его таким образом:

#if __name__ == '__main__':
web.run_app(app)

и я получил уведомление о no current event loop

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/IPython/core/interactiveshell.py", line 3293, in run_code
    async def run_code(self, code_obj, result=None, *, async_=False):
  File "<ipython-input-8-344f41746659>", line 13, in <module>
    web.run_app(app)
  File "/usr/local/lib/python3.8/site-packages/aiohttp/web.py", line 393, in run_app
    def run_app(app: Union[Application, Awaitable[Application]], *,
  File "/usr/local/Cellar/python@3.8/3.8.1/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asyncio/events.py", line 628, in get_event_loop
    def get_event_loop(self):
RuntimeError: There is no current event loop in thread 'Thread-11'.

Итак ... что можно запустить только в main? Я что-то здесь упускаю ..

Я попытался запустить в другом автономном скрипте, но в вспомогательном потоке:

def runWebapp():
  from aiohttp import web

  async def handle(request):
      name = request.match_info.get('name', "Anonymous")
      text = "Hello, " + name
      return web.Response(text=text)

  app = web.Application()
  app.add_routes([web.get('/', handle),
                  web.get('/{name}', handle)])
  web.run_app(app)

if __name__ == '__main__':
  from threading import Thread
  t = Thread(target=runWebapp)
  t.start()
  print('thread started let''s nap..')
  import time
  time.sleep(50)

Но это дает в основном ту же ошибку:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/local/Cellar/python@3.8/3.8.1/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/usr/local/Cellar/python@3.8/3.8.1/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/git/bluej/experiments/python/aio_thread.py", line 12, in runWebapp
    web.run_app(app)
  File "/usr/local/lib/python3.8/site-packages/aiohttp/web.py", line 409, in run_app
    loop = asyncio.get_event_loop()
  File "/usr/local/Cellar/python@3.8/3.8.1/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asyncio/events.py", line 639, in get_event_loop
    raise RuntimeError('There is no current event loop in thread %r.'
RuntimeError: There is no current event loop in thread 'Thread-1'.

Так как мне получить это веб-приложение из потока main и заставить его работать вместе с другими потоками в моем приложении

1 Ответ

1 голос
/ 01 апреля 2020

Здесь вы go:

import http.server
import threading
import socketserver

PORT = 8000

Handler = http.server.SimpleHTTPRequestHandler

def serve_forever():
    with socketserver.TCPServer(("", PORT), Handler) as httpd:
        httpd.serve_forever()

if __name__ == "__main__":
    threading.Thread(target=serve_forever).start()
    while 1:
        x = input("enter a number")
        print("You entered {}".format(x))

Обратите внимание, что это изящный прием для вечеринки, но не обязательно полезный для производственной работы: документация для модуля http.server написана пылающими красными буквами вверху страницы do c, чтобы не использовать ее в производстве. Но почти все платформы python веб-серверов работают как WSGI-серверы и не предназначены для работы так, как вы, кажется, этого хотите: они обычно ожидают, что их будет запускать что-то еще, например gunicorn или apache.

Я настоятельно рекомендую, если вам нужен HTTP-сервер, например, для мониторинга запущенного приложения, в котором вы используете asyncio и используете coros для всего, но вы можете развернуть свой собственный сценарий потоков, как указано выше, если вы действительно этого хотите. Вы можете видеть, что вы все еще можете взаимодействовать с оболочкой в ​​бесконечном вводе l oop, в то время как вы также можете свернуть localhost: 8000, чтобы получить страницу HTML, содержащую список каталогов.

Просто передайте нестандартный обработчик собственного создания, чтобы выполнять другие действия, такие как возврат состояния приложения в формате JSON.

...