AsyncClient makes a blocking call in its constructor, likely occurring in the Document.load method. This can cause the entire application to freeze until the client finishes this initial request.
Example script
This script includes both a function that blocks the event loop (make_request_blocking) and a workaround for that (make_request_non_blocking).
import asyncio
from zeep.client import AsyncClient
async def get_client_non_blocking():
return await asyncio.get_event_loop().run_in_executor(
None, AsyncClient, "http://172.16.1.45"
)
async def get_client_blocking():
""" I usually use the following pattern to create a client:
async with AsyncClient("http://172.16.1.45") as client:
return await client.service.serviceName(args="args")
"""
return AsyncClient("http://172.16.1.45")
async def counter():
for i in range(10):
print(i, flush=True)
await asyncio.sleep(1)
async def main():
# This one will block the event loop, and you should see
# only the first number printed
# await asyncio.gather(counter(), get_client_blocking())
# This one works as expected
await asyncio.gather(counter(), get_client_non_blocking())
if __name__ == "__main__":
asyncio.run(main())
Possible solution
Expose a def load() -> None function on Client and an async def load() -> None function on AsyncClient. Those functions could be called inside the __enter__ and __exit__ magic methods if they haven't been called yet.
Problem
AsyncClient
makes a blocking call in its constructor, likely occurring in theDocument.load
method. This can cause the entire application to freeze until the client finishes this initial request.Example script
This script includes both a function that blocks the event loop (
make_request_blocking
) and a workaround for that (make_request_non_blocking
).Possible solution
Expose a
def load() -> None
function onClient
and anasync def load() -> None
function onAsyncClient
. Those functions could be called inside the__enter__
and__exit__
magic methods if they haven't been called yet.