2017-08-08 57 views
0

所以我有一个接受输入ASYNCIO过程阻断

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) 

在这个例子中,它调用刽子手游戏,因为我有这个使用asyncio.sleep(n)测试不挡住任何东西,但是当我去到做一个基本的不和谐机器人它在hang子手中阻止它。

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秒左右(不长,但有很多用户发送垃圾邮件它是一个问题)机器人不接受任何其他消息

什么是我错过了能够让进程在后台运行,同时仍然接受新的输入?

回答

0

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

为了使过程实际上在后台运行,你可以尝试沿着线的东西:

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