Я пытаюсь прочитать данные индийского фондового рынка, используя вызовы API. В этом примере я использовал 10 акций. Моя текущая программа:
Сначала я определяю функцию:
def get_prices(stock):
start_unix = 1669794745
end_unix = start_unix + 1800
interval = 1
url = 'https://priceapi.moneycontrol.com/techCharts/indianMarket/stock/history?symbol=' + str(stock) + "&resolution = "+ str(interval) + "&from = " + str(start_unix) + "&to = " + str(end_unix)
url_data = requests.get(url).json()
print(url_data['c'])
Далее я использую многопоточность. Я мало что знаю о работе многопоточности — я просто использовал код из учебника в Интернете.
from threading import Thread
stocks = ['ACC','ADANIENT','ADANIGREEN','ADANIPORTS','ADANITRANS','AMBUJACEM','ASIANPAINT','ATGL','BAJAJ-AUTO','BAJAJHLDNG']
threads = []
for i in stocks:
threads.append(Thread(target=get_prices, args=(i,)))
threads[-1].start()
for thread in threads:
thread.join()
Время, необходимое для запуска вышеуказанной программы, составляет от 250 до 300 мс. На самом деле мне нужно будет запустить программу для тысяч акций. Есть ли способ заставить его работать быстрее. Я запускаю код в Jupyter Notebook на 8-ядерном чипе Apple M1. Любая помощь будет оценена. Спасибо!
@scotscotmcc Большое спасибо за ваш ответ. Да, время отклика сервера не зависит от меня. Но кроме этого, есть ли что-нибудь, что я могу сделать - программно? Может быть, использовать какую-то более продвинутую библиотеку многопоточности/многопроцессорности или внести некоторые изменения в приведенный выше код и т. д.?
Вы проверили этот веб-сайт, чтобы узнать, есть ли у них способ отправки массовых запросов, где вы можете запросить 20 или 50 результатов в одном запросе? ЭТО будет вашим лучшим планом для ускорения.






При извлечении данных из Интернета большая часть данных обычно тратится на ожидание ответов сервера. Чтобы выдавать большое количество запросов и получать ответы как можно быстрее, правильным подходом является параллельная выдача нескольких запросов. Чтобы быть максимально эффективным, вы должны найти правильный баланс между большим количеством параллельных запросов и регулированием (или занесением в черный список) удаленной службой.
В вашем коде вы создаете столько потоков, сколько есть запросов. В общем, вы хотели бы ограничить количество потоков и повторно использовать потоки после того, как они выполнили запрос, чтобы сэкономить ресурсы. Это называется пулом потоков.
Поскольку вы используете Python, другой более легкой альтернативой нескольким потокам является выполнение параллельных задач ввода-вывода с использованием asyncio в Python. Примеры реализации параллельных запросов с использованием пула потоков или asyncio показаны в этом ответе Stack Overflow.
Обновлено: вот адаптированный пример из вашего кода с использованием asyncio:
import asyncio
from aiohttp import ClientSession
stocks = ['ACC','ADANIENT','ADANIGREEN','ADANIPORTS','ADANITRANS','AMBUJACEM','ASIANPAINT','ATGL','BAJAJ-AUTO','BAJAJHLDNG']
async def fetch_price(session, stock, start_unix, end_unix, interval):
url = f'https://priceapi.moneycontrol.com/techCharts/indianMarket/stock/history?symbol = {stock}&resolution = {interval}&from = {start_unix}&to = {end_unix}'
async with session.get(url) as resp:
data = await resp.json()
return stock, data['c']
async def main():
start_unix = 1669794745
end_unix = start_unix + 1800
interval = 1
async with ClientSession() as session:
tasks = []
for stock in stocks:
tasks.append(loop.create_task(
fetch_price(session, stock, start_unix, end_unix, interval)
))
prices = await asyncio.gather(*tasks)
print(prices)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Огромное спасибо. Это сработало отлично. Пришлось дополнительно импортировать asyncio_nest вместе с вышеуказанной программой. Время стены сократилось примерно до 160-180 мс с 250-300 мс. Отлично! Пожалуйста, позвольте мне подождать еще некоторое время, чтобы отметить его как решенный. Я хочу посмотреть, есть ли другие способы сделать это быстрее. Еще раз большое спасибо за то, что приложили усилия для написания этого блестящего кода.
С помощью aiohttp и для большого количества запросов можно увеличить лимит параллельного запроса, передав явный коннектор в ClientSession.
проблема здесь, скорее всего, будет ответом с веб-сайта. То есть вы отправляете сообщение сайту и должны дождаться их ответа. Вы ничего не можете сделать, чтобы они реагировали быстрее, чтобы ваше сообщение распространялось быстрее, а их сообщения — быстрее. Вы можете отправить им сообщение с запросом на более чем одну акцию за раз — так что у вас будет только одна обратная связь вместо тысяч.