Created
September 16, 2019 15:13
-
-
Save fsbs/f31d81aa8ed1f78153c6c99179f9a075 to your computer and use it in GitHub Desktop.
Example of driving transfers with pycurl's multi.socket_action
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import asyncio | |
import pycurl | |
import selectors | |
MULTI = pycurl.CurlMulti() | |
SELECTOR = selectors.DefaultSelector() | |
LOOP = asyncio.get_event_loop() | |
TIMER = None | |
def socket_function(event, socket, multi, data): | |
print(f'\033[95msocket_function: event={event}, socket={socket}\033[0m') | |
if event == pycurl.POLL_REMOVE: | |
SELECTOR.unregister(socket) | |
else: | |
try: | |
SELECTOR.register(socket, event) | |
except KeyError: | |
SELECTOR.modify(socket, event) | |
def socket_timeout(): | |
print(f'\033[92msocket_timeout\033[0m') | |
return MULTI.socket_action(pycurl.SOCKET_TIMEOUT, 0) | |
def timer_function(timeout_ms): | |
global TIMER | |
print(f'\033[96mtimer_function: {timeout_ms}\033[0m') | |
if timeout_ms == -1: | |
TIMER.cancel() | |
else: | |
TIMER = LOOP.call_later(timeout_ms / 1000, socket_timeout) | |
return 0 | |
def write_function(data): | |
print(f'\033[93mwrite_function: {data}\033[0m') | |
async def main(): | |
# set callbacks for driving with multi-socket-action | |
MULTI.setopt(pycurl.M_SOCKETFUNCTION, socket_function) | |
MULTI.setopt(pycurl.M_TIMERFUNCTION, timer_function) | |
# init easy | |
easy = pycurl.Curl() | |
easy.setopt(pycurl.WRITEFUNCTION, write_function) | |
easy.setopt(pycurl.VERBOSE, 1) | |
easy.setopt(pycurl.URL, 'https://nghttp2.org/httpbin/drip?duration=1&numbytes=10&code=200&delay=1') | |
# the following should call timer_function which would start the transfer | |
MULTI.add_handle(easy) | |
await asyncio.sleep(0) | |
run_count = 1 | |
# but have to init the transfer explicitly | |
_, run_count = socket_timeout() | |
# drive the transfer with multi-socket-action | |
while run_count: | |
await asyncio.sleep(0) | |
for key, event in SELECTOR.select(timeout=None): | |
await asyncio.sleep(0) | |
_, run_count = MULTI.socket_action(key.fd, event) | |
# close easy | |
easy.close() | |
MULTI.remove_handle(easy) | |
LOOP.run_until_complete(main()) | |
MULTI.close() | |
SELECTOR.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment