python-zeep
python-zeep copied to clipboard
AsyncClient has a blocking constructor
Problem
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.