2

I am running a program that makes three different requests from a rest api. data, indicator, request functions all fetch data from BitMEX's api using a wrapper i've made.

I have used asyncio to try to speed up the process so that while i am waiting on a response from previous request, it can begin to make another one.

However, my asynchronous version is not running any quicker for some reason. The code works and as far as I know, I have set everything up correctly. But there could be something wrong with how I am setting up the coroutines?

Here is the asynchronous version:

import time
import asyncio

from bordemwrapper import BitMEXData, BitMEXFunctions


'''
asynchronous I/O
'''

async def data():
    data = BitMEXData().get_ohlcv(symbol='XBTUSD', timeframe='1h', 
                                  instances=25)
    await asyncio.sleep(0)
    return data

async def indicator():
    indicator = BitMEXData().get_indicator(symbol='XBTUSD', 
        timeframe='1h', indicator='RSI', period=20, source='close', 
        instances=25)
    await asyncio.sleep(0)
    return indicator

async def request():
    request = BitMEXFunctions().get_price()
    await asyncio.sleep(0)
    return request

async def chain():
    data_ = await data()
    indicator_ = await indicator()
    request_ = await request()
    return data_, indicator_, request_

async def main():
    await asyncio.gather(chain())

if __name__ == '__main__':
    start = time.perf_counter()
    asyncio.run(main())
    end = time.perf_counter()

    print('process finished in {} seconds'.format(end - start))
1
  • 3
    In addition to Josh's response, your chain coroutine is written to await the three downloads in sequence. Even if they were using asyncio correctly, you would get sequential downloading. To fix this (after switching to actually using asyncio as indicated by Josh), chain needs to await gather(data(), indicator(), request(), and only then will the three run in parallel. Calling gather with a single coroutine, as done in main() serves no purpose and is equivalent to just awaiting the coroutine directly. Commented Jun 16, 2019 at 8:38

1 Answer 1

5

Unfortunately, asyncio isn't magic. Although you've put them in async functions, the BitMEXData().get_<foo> functions are not themselves async (i.e. you can't await them), and therefore block while they run. The concurrency in asyncio can only occur while awaiting something.

You'll need a library which makes the actual HTTP requests asynchronously, like aiohttp. It sounds like you wrote bordemwrapper yourself - you should rewrite the get_<foo> functions to use asynchronous HTTP requests. Feel free to submit a separate question if you need help with that.

Sign up to request clarification or add additional context in comments.

1 Comment

ah yes, i see now. been reading the aiohttp docs and going to try it out, thanks so much for your help

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.