tornadoweb / tornado

Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed.
http://www.tornadoweb.org/
Apache License 2.0
21.77k stars 5.51k forks source link

CurlAsyncHTTPClient hangs #3175

Open saltedsword opened 2 years ago

saltedsword commented 2 years ago

It hangs when executing method fetch with CurlAsyncHTTPClient. I tried working on CentOS, Python 3.7 ~ 3.9, but the behavior was the same.

However, when i use SimpleAsyncHTTPClient, it works fine.

Software environment:

Here is my test code:

import asyncio
from tornado.httpclient import AsyncHTTPClient
AsyncHTTPClient.configure('tornado.curl_httpclient.CurlAsyncHTTPClient', max_clients=10)

http_client = AsyncHTTPClient()
async def main():
  print('fetch...')
  res = await http_client.fetch('http://localhost')
  print('res', len(res.body))

asyncio.run(main())

I wonder if my code is wrong, since no one mentioned the same issue.

bdarnell commented 2 years ago

Your code looks fine to me. It's not quite the same behavior but I wonder if this could be related to #3131 (different versions of everything, though).

Try enabling asyncio's debug mode and setting the logging level to debug to see more about what's going on.

alex-ip commented 1 year ago

G'day - I came up against the same problem. It had me stumped, because I could run the sample code for the e web-spider example in https://buildmedia.readthedocs.org/media/pdf/tornado/latest/tornado.pdf with no issues.

What I found was that when I pre-instantiated the AsyncHTTPClient, the fetch failed, but when I instantiated it on the fly, it worked.

The modified version of @saltedsword's code that now works is as follows:

import asyncio
import logging
from tornado.httpclient import AsyncHTTPClient
AsyncHTTPClient.configure('tornado.curl_httpclient.CurlAsyncHTTPClient', max_clients=10)

LOG_LEVEL = logging.DEBUG
root_logger = logging.getLogger()
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter("%(asctime)s %(name)s %(levelname)s %(message)s"))
root_logger.addHandler(handler)
root_logger.setLevel(LOG_LEVEL)

logger = logging.getLogger(__name__)
logger.setLevel(LOG_LEVEL)

tornado_logger = logging.getLogger('tornado.curl_httpclient')
tornado_logger.setLevel(LOG_LEVEL)

asyncio_logger = logging.getLogger("asyncio")
asyncio_logger.setLevel(LOG_LEVEL)

url = "http://www.tornadoweb.org/en/stable/"

http_client = AsyncHTTPClient()
async def main():
  print(f'fetching {url}')
  #res = await http_client.fetch(url)
  res = await AsyncHTTPClient().fetch(url)
  print('res', len(res.body))

asyncio.run(main(), debug=True)

It looks to me like the instantiation only works when there is an open, running IOloop, i.e. if it happens inside a running coroutine.