Discord.py 机器人,我可以做一个繁重的任务 "off to the side" 这样我就不会延迟输入吗?
Discord.py bot, can I do a heavy task "off to the side" so I don't lag inputs?
我在 Python / Discord.py 中有一个 Discord 机器人,人们可以在其中输入命令,而且机器人通常会非常快速地响应。
然而,机器人在主循环的每次迭代中也是 gathering/scraping 网络数据。通常情况下,抓取非常简短,所以没有人真正注意到,但有时代码会被设置为进行更彻底的抓取,这会花费更多时间。但是在这些繁重的抓取过程中,机器人对用户命令有点反应迟钝。
@bot.command()
async def sample_command(ctx):
# may actually take a while for this command to respond if we happen to be
# in the middle of a heavier site scrape
await ctx.channel.send("Random message, something indicating bot has responded")
async def main_loop():
sem = asyncio.Semaphore(60)
connector = aiohttp.TCPConnector(limit=60)
async with aiohttp.ClientSession(connector=connector, headers=headers) as session:
while True:
# main guts of loop here ...
scrapers = [scraper_1(session, sem), scraper_2(session, sem), ...]
data = list(chain(*await asyncio.gather(*scrapers))) # this may take a while
# do stuff with data
有没有办法让它继续“嘿,你想做一个沉重的刮擦,好的去别处处理它 - 同时让我们继续主循环,稍后我会与你联系大功告成,然后我们将处理数据”,如果这有意义的话?
我主要想分开这个抓取步骤,这样它就不会阻碍人们与机器人的其余部分进行实际交互的能力。
你可以尝试使用python线程。
了解更多here
它基本上允许您 运行 它在不同的线程上
示例:
import threading
def 1():
print("Helo! This is the first thread")
def 2():
print("Bonjour! This is the second thread")
thread1 = threading.Thread(target=1)
thread2 = Threading.Thread(target=2)
thread1.start()
thread2.start()
您可以使用 discord.py 任务扩展 docs。
例如:
from discord.ext import tasks
@bot.event()
async def on_ready():
main_loop.start()
@bot.command()
async def sample_command(ctx):
await ctx.channel.send("Random message, something indicating bot has responded")
@tasks.loop(seconds=60)
async def main_loop():
do_something()
注意:不建议在on_ready开始任务,因为bot会重新连接到discord,任务会开始好几次,把它放在别的地方或者on_ready检查这是不是第一个连接。
另一个简单提示:您可以使用 await ctx.send()
而不是 await ctx.channel.send()
您可以使用 asyncio.create_task()
在“后台”生成抓取:
async def scrape_and_process(...):
scrapers = [scraper_1(session, sem), scraper_2(session, sem), ...]
data = list(chain(*await asyncio.gather(*scrapers))) # this may take a while
# do stuff with data
async def main_loop():
sem = asyncio.Semaphore(60)
connector = aiohttp.TCPConnector(limit=60)
async with aiohttp.ClientSession(connector=connector, headers=headers) as session:
while True:
# main guts of loop here ...
# initiate scraping and processing in the background and
# proceed with the loop
asyncio.create_task(scrape_and_process(...))
我在 Python / Discord.py 中有一个 Discord 机器人,人们可以在其中输入命令,而且机器人通常会非常快速地响应。
然而,机器人在主循环的每次迭代中也是 gathering/scraping 网络数据。通常情况下,抓取非常简短,所以没有人真正注意到,但有时代码会被设置为进行更彻底的抓取,这会花费更多时间。但是在这些繁重的抓取过程中,机器人对用户命令有点反应迟钝。
@bot.command()
async def sample_command(ctx):
# may actually take a while for this command to respond if we happen to be
# in the middle of a heavier site scrape
await ctx.channel.send("Random message, something indicating bot has responded")
async def main_loop():
sem = asyncio.Semaphore(60)
connector = aiohttp.TCPConnector(limit=60)
async with aiohttp.ClientSession(connector=connector, headers=headers) as session:
while True:
# main guts of loop here ...
scrapers = [scraper_1(session, sem), scraper_2(session, sem), ...]
data = list(chain(*await asyncio.gather(*scrapers))) # this may take a while
# do stuff with data
有没有办法让它继续“嘿,你想做一个沉重的刮擦,好的去别处处理它 - 同时让我们继续主循环,稍后我会与你联系大功告成,然后我们将处理数据”,如果这有意义的话?
我主要想分开这个抓取步骤,这样它就不会阻碍人们与机器人的其余部分进行实际交互的能力。
你可以尝试使用python线程。
了解更多here
它基本上允许您 运行 它在不同的线程上
示例:
import threading
def 1():
print("Helo! This is the first thread")
def 2():
print("Bonjour! This is the second thread")
thread1 = threading.Thread(target=1)
thread2 = Threading.Thread(target=2)
thread1.start()
thread2.start()
您可以使用 discord.py 任务扩展 docs。
例如:
from discord.ext import tasks
@bot.event()
async def on_ready():
main_loop.start()
@bot.command()
async def sample_command(ctx):
await ctx.channel.send("Random message, something indicating bot has responded")
@tasks.loop(seconds=60)
async def main_loop():
do_something()
注意:不建议在on_ready开始任务,因为bot会重新连接到discord,任务会开始好几次,把它放在别的地方或者on_ready检查这是不是第一个连接。
另一个简单提示:您可以使用 await ctx.send()
而不是 await ctx.channel.send()
您可以使用 asyncio.create_task()
在“后台”生成抓取:
async def scrape_and_process(...):
scrapers = [scraper_1(session, sem), scraper_2(session, sem), ...]
data = list(chain(*await asyncio.gather(*scrapers))) # this may take a while
# do stuff with data
async def main_loop():
sem = asyncio.Semaphore(60)
connector = aiohttp.TCPConnector(limit=60)
async with aiohttp.ClientSession(connector=connector, headers=headers) as session:
while True:
# main guts of loop here ...
# initiate scraping and processing in the background and
# proceed with the loop
asyncio.create_task(scrape_and_process(...))