2017-08-08 87 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)))