Asyncio进程阻塞

时间:2017-08-08 16:10:55

标签: python asynchronous

所以我有一个基本的discord bot接受输入

import discord
import asyncio
import threading

loop = asyncio.new_event_loop()
bot  = discord.Client()

def run_asyncio_loop(loop):
    asyncio.set_event_loop(loop)
    loop.run_forever()

Hangman.set_bot(bot)

@bot.event
async def on_message(message):
    bot.loop.create_task(Hangman.main(message))


asyncioLoop = threading.Thread(target = run_asyncio_loop, args = (loop,))
asyncioLoop.start()

bot.run(BotConstants.TOKEN)

在这个例子中,它调用了hangman游戏,它不会阻止任何东西,因为我使用asyncio.sleep(n)测试了这个但是当我在hangman中做某事时会阻止它。

class Hangman():
    async def main(message):
        await Hangman.make_guess(message)

    async def update_score(message):
        sheetLoaded = Spreadsheet.load_ws(...)
            userExists = Spreadsheet.user_exists(...)
            if (not userExists):
                Spreadsheet.add_user(...)
            Spreadsheet.add_score(...)
            await Hangman.bot.send_message(message.channel, msg)

        elif (not sheetLoaded):
            await Hangman.bot.send_message(message.channel, msg)

    async def make_guess(message):

        # perform guess

        if (matched):      
            await Hangman.bot.send_message(message.channel, msg)
            Hangman.GAMES.pop(message.server.id)
            await Hangman.update_score(message)

调用Hangman.update_score()时会阻止它。所以它不会处理任何命令,直到分数更新,这意味着大约5秒左右(不长但很多用户发送垃圾邮件是一个问题)机器人不接受任何其他消息

我还缺少什么能让这个过程在后台运行同时仍接受新的输入?

1 个答案:

答案 0 :(得分:1)

Asyncio仍然是单线程的。事件循环运行的唯一方法是没有其他协同程序正在执行。使用from / await中的yield会暂时挂起协同程序,从而为事件循环提供工作机会。因此,除非您使用yield (from)awaitreturn调用其他协程,否则会阻止该进程。您可以在await asyncio.sleep(0)的步骤之间添加Hangman.update_score,以便在多个部分中划分流程阻止,但这只能确保减少“挂起”时间,而不会实际加快您的线程。

要使该过程实际在后台运行,您可以尝试以下方式:

from concurrent.futures import ProcessPoolExecutor
executor = ProcessPoolExecutor(2)
asyncio.ensure_future(loop.run_in_executor(executor, Hangman.update_score(message)))