【问题标题】:Is there a way to improve speed with for loops有没有办法通过 for 循环提高速度
【发布时间】:2021-02-19 22:04:52
【问题描述】:

我需要发布一系列 XML 元素(每次调用的数量可能不同)。我在 Python 3.9.1 上使用 Requests v2.25.1。虽然我的解决方案有效,但它需要大约 27 秒才能执行,尽管请求模块显示 r.elapsed 不到 1 秒即可完成。我已经验证的事情:

  • r.text 编码问题不存在
  • 头信息正确
  • 创建 requests.Session() 不会缩短响应时间

运行 Postman 时,我也看到不到 1 秒的结果。我已将此问题隔离到我正在运行的for loop。数据从 SQL 中提取,存储为变量,然后 for 循环对其进行处理并在我的 XML 请求中运行。

我的问题是我的以下代码是否是最佳实践,或者是否有更“pythonian”的方式来完成我想要完成的任务?任何指导表示赞赏。

    skill_id=[]
    agent_state=[]
    agent_name=[]

    for db_users in db_results:
       skill_id.append(db_users[0])
       agent_state.append(db_users[1])
       agent_name.append(db_users[2])
    if db_users[1] == 'NOT_READY':
       try:
            cursor.execute(sqlskillgroup)
            skillgroups = []
            for sg_query_result in cursor.fetchall():
                sg = sg_query_result[0]
                skillgroups.append(sg)

    except pyodbc.Error as e:
            print("Error retreiving skill group information from database.")
            quit()

    finally:
        connect.close()
    icm_url = "https://url_of_post"
    xmlfile = open('skill_remove.xml', 'r')
    body = xmlfile.read()
    icm_header = {
           'Content-Type': 'application/xml',
           'Authorization': 'Basic Q2hhZF9NZXllckBhamcuY29tOmNpc2Nv',
           'Cookie': 'JSESSIONID=0C8456E3901DF7A3A0862E17FD50547D'
           }

    for sgid in skillgroups:
        r = requests.request("POST",icm_url, headers = icm_header,
            data = body.format(agent = str(skill_id[0]), skill_urls = '<refURL>/unifiedconfig/config/skillgroup/' + str(sgid) + '</refURL>',),
            verify = r"CAchain.pem",
            cert = (r"cert.cer", r"cert.key"),
            )

    print(r.text)
    print(r.elapsed)

  

【问题讨论】:

  • 为什么你有三个列表 - 只有一个包含所有 3 个项目的列表。如果您预先构建一些数据项(例如可能的主体),最后一个 for 循环可能会更快。 - 很难确切地看到问题是什么......
  • if db_users[1] == 'NOT_READY':的标识可以吗?
  • @TonySuffolk66 不确定如何将所有列表项合并为 1 并单独调用它们。正文大部分是在外部文件中创建的,我将“代理”和“sgid”值传递到该文件中以进行 POST。
  • @Ivan - 你能澄清一下吗?如果您的意思是缩进,那么所有这些在我的脚本中的格式都是正确的。
  • 技能组中有多少个列表项?打印r.elapsed 只会显示最新请求经过的时间,而不是累积的。如果你有很多要求,你真的应该研究 asyncio。您遇到的网络服务器问题是您的机器空闲的每个后续请求之间的延迟,等待消息来回传递

标签: python loops python-requests


【解决方案1】:

看起来您正在计时循环中最后一个请求的经过时间。您可以通过将r.elapsed 移动到循环中并对每个请求求和,或者通过添加到循环中的运行总计并在最后打印来计算总运行时间。

total_elapsed = 0
   for sgid in skillgroups:
    r = requests.request("POST",icm_url, headers = icm_header,
            data = body.format(agent = str(skill_id[0]), skill_urls = '<refURL>/unifiedconfig/config/skillgroup/' + str(sgid) + '</refURL>',),
            verify = r"CAchain.pem",
            cert = (r"cert.cer", r"cert.key"),
            )
    total_elapsed += r.elapsed

基本的 asyncio 和 aiohttp 实现

import asyncio
import aiohttp

async def post_request(session, url):
    async with session.post() as request: #add your request headers, certificate etc
        await request.status

async def main():
    async with aiohttp.ClientSession() as session: # use client session to auto close at the end
        tasks = []
        for url in urls:
            t = asyncio.create_task(post_request(session, url)) #create a number of tasks to run concurrently
            tasks.append(t)

        await asyncio.gather(*tasks) # wait for all tasks to finish before close the session

asyncio.run(main())

【讨论】:

  • 在让 aiohttp 发布文件时遇到问题,但看起来这可能是一个可行的解决方案。感谢大家的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-18
  • 2019-08-01
  • 2020-12-01
  • 1970-01-01
  • 2018-08-06
  • 1970-01-01
  • 2012-04-18
相关资源
最近更新 更多