Skip to content

Instantly share code, notes, and snippets.

@fsbs
Created September 16, 2019 15:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fsbs/f31d81aa8ed1f78153c6c99179f9a075 to your computer and use it in GitHub Desktop.
Save fsbs/f31d81aa8ed1f78153c6c99179f9a075 to your computer and use it in GitHub Desktop.
Example of driving transfers with pycurl's multi.socket_action
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