如何使此代码运行得更好/更快(线程或多处理)?怎么做?

Posted

技术标签:

【中文标题】如何使此代码运行得更好/更快(线程或多处理)?怎么做?【英文标题】:How can I make this code run better/faster (threading or multiprocessing)? And how can it be done? 【发布时间】:2019-08-12 14:53:15 【问题描述】:

我有一个简单的机器人,它使用 cookie 登录网站并检查商品的价格,如果该价格符合我设置的价格,它就会购买该商品。

我正在寻找提高此机器人速度的方法。我真的不知道在这种情况下多处理是否会让这个机器人更快。

我也在寻找提高效率的方法。

session = requests.session()
session.cookies["cookie"] = ""

log_in = session.get("https://www.example.com")
if log_in.status_code == 200:
    print("Logged In")
else:
    raise ValueError("Invalid Cookie")

crsf_token = ""

def token():
    global crsf_token
    while True:
        crsf_token = re.search(r"<script>XsrfToken.setToken\('(.*?)'\);</script>", session.get('https://www.example.com').text).group(1)
        time.sleep(5)

def _cthread():
    while True:
        try:
            req = session.get(f"https://www.example.com/productID")
            if req.status_code == 429:
                time.sleep(5)
                continue

            for i in req.json()["data"]["Sellers"]:
                if i["Price"] <= 300:
                    session.post(f'https://www.example.com&expectedPrice=i["Price"]&expectedSellerID=i["SellerId"]&userAssetID=i["UserAssetId"]', headers="X-CSRF-TOKEN": crsf_token)
        except requests.urllib3.exceptions.ConnectTimeoutError as E:
            pass


while True:
    threading.Thread(target=_cthread).start()
    threading.Thread(target=token).start()

我在这方面没有取得太大的成功,但它现在确实有效。

【问题讨论】:

我相信您只执行一项任务。你认为多线程有什么好处? @BlueRineS:可能有助于为响应每个GET而提交的大量POST请求。 【参考方案1】:

假设您不受带宽限制,并且该站点不会一次关闭太多提交的 POSTs,您可能会通过线程化您的 post 调用获得一点好处,更改:

        for i in req.json()["data"]["Sellers"]:
            if i["Price"] <= 300:
                session.post(f'https://www.example.com&expectedPrice=i["Price"]&expectedSellerID=i["SellerId"]&userAssetID=i["UserAssetId"]', headers="X-CSRF-TOKEN": crsf_token)

到:

        allposts = [f'https://www.example.com&expectedPrice=i["Price"]&expectedSellerID=i["SellerId"]&userAssetID=i["UserAssetId"]'
                    for i in req.json()["data"]["Sellers"] if i["Price"] <= 300]
        if allposts:
            with Pool() as pool:
                pool.map(partial(session.post, headers="X-CSRF-TOKEN": crsf_token), allposts)

将以下导入添加到文件顶部:

from multiprocessing.dummy import Pool  # Gets thread based worker Pool class
from functools import partial           # Lets you bind headers up front so you only need to pass URL to post

为避免过多的线程产生,您可以在该函数的循环外创建pool,而不是仅在allposts 非空时按需创建。

我还建议从代码的顶层删除while True:token_cthread 已经是无限循环,因此拥有这两个循环意味着产生无限数量的线程,每个线程都永远运行,而您实际上只需要两个持久线程。

【讨论】:

感谢您的好评!你能告诉我如何在循环之外创建多处理池吗?我从这两个函数中删除了while True:。但是绝对cpu使用率很高 @EdwinTan:你不想从函数中删除它,你想从顶层删除它(没有理由让多个线程同时尝试GET )。在循环外创建它与在循环内创建它相同,只需将 with Pool() as pool: 移到 while 之外并缩进 while 及其内容即可。【参考方案2】:

尝试从函数token()_cthread()中删除while True

【讨论】:

为什么?我认为最好从主模块中删除 while True ,因为线程应该只启动一次.. @BlueRineS 这不会有帮助,他最终会用一个线程工作,而 Rk003 的解决方案可以工作,因为它将停止无休止地创建几乎永远不会停止的线程。 @a-sam:从函数中删除它意味着在顶层产生无限线程;很可能线程生成将比网络请求更快,因此程序在线程用完时会崩溃。您只需要两个***线程,每个线程都可以永远运行,而不会产生永远不会清理的新线程。 OP 说I am looking for ways to improve the speed of this bot 所以我认为这是更好的方法。

以上是关于如何使此代码运行得更好/更快(线程或多处理)?怎么做?的主要内容,如果未能解决你的问题,请参考以下文章

更快更好用的Redis6.0

如何使此 Java 代码正常运行? [多线程,竞争条件]

如何让已经运行的 PL SQL 包运行得更快?

如何在 C++ 中使 csv 文件运行得更快

如何使用 CommonDataKinds.Phone 内部查询使此 ContactsContract.Contact 查询更快?

为啥很少有人输入 const 正确的代码? const 正确的代码会编译得更好/更快吗? [关闭]