首页 > 解决方案 > Python异步等待问题

问题描述

经过研究,我决定使用 asyncio 来更快地获取数千个 API 请求。

async def get_marketcap(session, ticker, marketcap):
    url = "https://api.polygon.io/vX/reference/tickers/" + ticker +"&apiKey=" + profile.POLYGON_API_KEY
    async with session.get(url, ssl=False) as response:
        text = await response.json()
        marketcap[ticker] = text['results']['market_cap']

async def scan(api):
    df = pd.read_csv('./data/tickers/polygon_list.csv')

    tickers = df['ticker'].tolist()

    marketcap = {}

    async with aiohttp.ClientSession() as session:
        tasks = [get_marketcap(session, ticker, marketcap) for ticker in tickers]
        await asyncio.gather(*tasks)

    return marketcap

这会从 csv 文件中获取股票代码列表,并使用 aiohttp 执行大约 9,000 个 API 请求,以从 JSON 响应中获取每个代码的市值。(我设置 ssl=False 因为它之前给了我一个 SSL 错误)

Asyncio.run(scan(api))

从不同的 python 文件调用。

Traceback (most recent call last):
  File "/Users/jakeyoon/Documents/Python Programs/Trade Bot/trader.py", line 22, in <module>
    tickers = asyncio.run(test.scan(api))
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
    return future.result()
  File "/Users/jakeyoon/Documents/Python Programs/Trade Bot/test.py", line 25, in scan
    await asyncio.gather(*tasks)
  File "/Users/jakeyoon/Documents/Python Programs/Trade Bot/test.py", line 12, in get_marketcap
    with session.get(url, ssl=False) as response:
AttributeError: __enter__

这是我得到的错误......我也试过

asyncio.ensure_future()

这修复了下面的错误,但由于某种我不明白的原因给了我一个 KeyError ['results'] ......肯定有一个属性'result'。我一直在查看多个堆栈溢出帖子、YouTube 和教程,但仍然无法理解问题所在。似乎 asyncio 经常更新,所以我不确定使用的最佳方法和实践是什么。

你能帮我理解什么是错的或更好地理解 asychio 概念吗?谢谢!

标签: pythonasynchronousasync-awaitpython-asyncioaiohttp

解决方案


设置 ssl=False 不是一个好的解决方法,因为 API 似乎发生了变化,并且说无法建立 SSL 握手

Install Certificates.command

对我不起作用,所以必须复制并粘贴 python 文件并独立运行

# install_certifi.py
#
# sample script to install or update a set of default Root Certificates
# for the ssl module.  Uses the certificates provided by the certifi package:
#       https://pypi.python.org/pypi/certifi

import os
import os.path
import ssl
import stat
import subprocess
import sys

STAT_0o775 = ( stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR
             | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP
             | stat.S_IROTH |                stat.S_IXOTH )


def main():
    openssl_dir, openssl_cafile = os.path.split(
        ssl.get_default_verify_paths().openssl_cafile)

    print(" -- pip install --upgrade certifi")
    subprocess.check_call([sys.executable,
        "-E", "-s", "-m", "pip", "install", "--upgrade", "certifi"])

    import certifi

    # change working directory to the default SSL directory
    os.chdir(openssl_dir)
    relpath_to_certifi_cafile = os.path.relpath(certifi.where())
    print(" -- removing any existing file or link")
    try:
        os.remove(openssl_cafile)
    except FileNotFoundError:
        pass
    print(" -- creating symlink to certifi certificate bundle")
    os.symlink(relpath_to_certifi_cafile, openssl_cafile)
    print(" -- setting permissions")
    os.chmod(openssl_cafile, STAT_0o775)
    print(" -- update complete")

if __name__ == '__main__':
    main()
task = asyncio.ensure_future(get_marketcap(session, ticker, marketcap))
tasks.append(task)


Asyncio.gather(*tasks)

也修复了问题

根据评论中的建议,我添加了 try 异常以捕获 404 或其他 API 错误,并且我的代码确实有 async ,但仍然给出了错误,但我猜堆栈跟踪是之前复制的。

谢谢!


推荐阅读