httpx requests cancelling outer tasks #3154
-
import asyncio
import httpx
async def ping():
async with httpx.AsyncClient(timeout=1.0) as client:
try:
url = "http://httpbin.org/get"
resp = await client.get(url)
except Exception as e:
print(repr(e))
else:
print(resp.status_code)
async def loop():
while True:
await asyncio.sleep(3)
await ping()
async def spawn_task():
task = asyncio.create_task(loop())
while True:
await asyncio.sleep(3)
print("is cancelling: ", task.cancelling())
print("state: ", task._state)
asyncio.run(spawn_task()) The code above will print something like:
Somehow httpx increases the number of cancellation requests to the task it doesn't own.
This doesn't cause a direct issue (so far), but I find it strange that httpx tries to cancel an outer task when there's no |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 3 replies
-
I can isolate this down further... import asyncio
import httpcore
origin = httpcore.URL("http://www.example.com").origin
async def ping():
async with httpcore.AsyncHTTPConnection(origin) as connection:
try:
url = "http://www.example.com"
resp = await connection.request("GET", url)
except Exception as e:
print(repr(e))
else:
print(resp.status)
async def loop():
while True:
await asyncio.sleep(3)
await ping()
async def spawn_task():
task = asyncio.create_task(loop())
while True:
await asyncio.sleep(3)
print("is cancelling: ", task.cancelling())
print("is done: ", task.done())
print("state: ", task._state)
asyncio.run(spawn_task()) I don't know what that's about, or how to figure out if that's an Is there a way to inspect where in the stacktrace those cancellations are? |
Beta Was this translation helpful? Give feedback.
-
Good call about stacktrace, I was able to override and add logging: import asyncio
import httpcore
origin = httpcore.URL("http://www.example.com").origin
async def ping():
async with httpcore.AsyncHTTPConnection(origin) as connection:
try:
url = "http://www.example.com"
resp = await connection.request("GET", url)
except Exception as e:
print(repr(e))
else:
print(resp.status)
async def loop():
while True:
await asyncio.sleep(3)
await ping()
async def spawn_task():
task = asyncio.create_task(loop(), name="loop task")
og_cancel = task.cancel
def new_cancel(msg = None):
import traceback
traceback.print_stack()
print(msg)
return og_cancel(msg)
task.cancel = new_cancel
while True:
await asyncio.sleep(3)
print("is cancelling: ", task.cancelling())
print("is done: ", task.done())
print("state: ", task._state)
asyncio.run(spawn_task()) Getting |
Beta Was this translation helpful? Give feedback.
I can isolate this down further...