AsyncCurlMulti Object

Note

The AsyncCurlMulti API is experimental and may change in a future release.

class pycurl.AsyncCurlMulti(close_handles=False) AsyncCurlMulti object

An asyncio-driven wrapper around pycurl.CurlMulti. Each pycurl.Curl transfer is represented by an asyncio.Future that resolves to the same Curl object on success or raises pycurl.error on failure.

The constructor does not require a running event loop; the loop is captured on the first call to add_handle() and the instance is bound to that loop for its lifetime.

A selector-style asyncio event loop is required. On a non-selector loop (e.g., Windows ProactorEventLoop) add_handle() raises RuntimeError with guidance on switching policy.

Always call aclose() (or use async with) to release the underlying multi handle promptly.

close_handles is forwarded to pycurl.CurlMulti. When True, any easy handle still attached to the multi when aclose() runs is also closed by libcurl.

Example:

async with pycurl.AsyncCurlMulti() as multi:
    curl = pycurl.Curl()
    curl.setopt(pycurl.URL, "https://example.com")
    await multi.perform(curl)
    print(curl.getinfo(pycurl.RESPONSE_CODE))

Batch example:

async with pycurl.AsyncCurlMulti() as multi:
    for url in urls:
        curl = pycurl.Curl()
        curl.setopt(pycurl.URL, url)
        multi.add_handle(curl)
    results = await asyncio.gather(*multi.futures())

AsyncCurlMulti objects have the following methods:

__init__(close_handles: bool = False) None
setopt(option, value) None

Sets a multi-handle option. Equivalent to pycurl.CurlMulti.setopt(), except that M_SOCKETFUNCTION, M_TIMERFUNCTION, and (on libcurl 8.17.0+) M_NOTIFYFUNCTION are owned by AsyncCurlMulti and raise ValueError if set externally.

option is a pycurl.M_* constant identifying which option to set. value is the new option value; different options accept values of different types (see pycurl.CurlMulti.setopt()).

add_handle(curl) asyncio.Future

Schedules curl for transfer and returns an asyncio.Future that resolves to curl on success or raises pycurl.error on failure. Cancelling the future removes the handle; cleanup runs on the next event-loop tick.

curl is a pycurl.Curl easy handle.

The first call captures the running event loop and binds this instance to it. Raises RuntimeError if called outside a running loop, after aclose(), or if curl is already registered.

remove_handle(curl) None

Removes curl from this multi handle and cancels its future (if not already done). Synchronous; if you need to observe the cancellation propagate, await the future returned from the original add_handle() call.

curl is a pycurl.Curl easy handle. Raises RuntimeError if curl is not registered or after aclose(). Raises pycurl.error if libcurl rejects the removal.

async perform(curl) Curl object

Coroutine equivalent to await self.add_handle(curl). Schedules curl for transfer and returns it once the transfer completes. Raises pycurl.error on failure.

curl is a pycurl.Curl easy handle.

futures(curls=None) tuple of asyncio.Future

Returns a snapshot of futures for transfers currently registered with this multi handle.

curls is either None (the default) or an iterable of pycurl.Curl easy handles. When None, the result contains every pending future in the order in which the handles were added via add_handle(). When an iterable is given, the result contains the corresponding futures in input order and length (so duplicates yield duplicate references to the same future).

Completed or cancelled transfers are not included in later snapshots.

Raises KeyError if any handle in curls is not currently registered.

async aclose() None

Coroutine. Cancels the pending timer, removes all in-flight handles, unregisters socket watchers, and closes the underlying multi handle. Pending futures are cancelled. Idempotent.

closed

Whether the underlying pycurl.CurlMulti handle is closed.

async __aenter__() AsyncCurlMulti
async __aexit__(exc_type: type[BaseException] | None, exc: BaseException | None, tb: Any) None