如何使此代码运行得更好/更快(线程或多处理)?怎么做?
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】:
假设您不受带宽限制,并且该站点不会一次关闭太多提交的 POST
s,您可能会通过线程化您的 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
所以我认为这是更好的方法。以上是关于如何使此代码运行得更好/更快(线程或多处理)?怎么做?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 CommonDataKinds.Phone 内部查询使此 ContactsContract.Contact 查询更快?