如何在并发运行的函数中一次执行一部分代码?

2024-10-01 00:17:00 发布

您现在位置:Python中文网/ 问答频道 /正文

所以,让我给你们简要介绍一下我试图实现的目标。我有一个名为apply的命令,只要有人输入该命令,apply函数的执行就会开始。现在,apply函数有一部分代码,我想并发执行,以防多个用户同时触发该命令,还有一个名为register的异步函数,我想一次执行一次。以下是代码简介:

@client.command()
async def apply(ctx):
 #Stuff I want to be run concurrently
 await register(ctx.author)

async def register(user):
 # I've an another python file 'db.py' for accessing the database 
 data = await db.execute_query('SELECT Total_Reg from Data WHERE rowid = 1')
 total = data[0][0] # Getting the total registrations value and storing it in total variable     
 if total >= max_reg: # If total reg. are more or equal to max value then close the reg.
  print("Registrations are closed!")
  return
 # Otherwise if registrations are open then increase the value of total reg by 1
 # And register the user with unique registration number [reg_no] allotted to him
 await db.execute_query('UPDATE Data SET Total_Reg = Total_Reg + 1 WHERE rowid = 1')
 reg_no = total + 1
 registrations[reg_no] = user
 await close_registration() 
 """Also, in case of Queue or execution of this function once at a time, I 
    want this function to continue executing the code and shouldn't wait for 
    this line of code particularly, i.e await close_registration() should 
    keep on executing in background without blocking the current execution of 
    this function. So should I use asyncio.ensure_future(close_registration()) 
    instead of await or what?"""

我希望你明白我在这里想做什么。现在,让我们来回答我的问题。 apply函数会在有人输入apply命令时由discord触发,因此data = await db.execute_query('SELECT Total_Reg from Data WHERE rowid = 1')可能会在同一时间执行多次,这将导致返回相同数量的注册,并存储在所有注册的total变量中

我知道,当已经有一个连接正在更新或访问数据库时,sqlite会锁定数据库,但是,一旦执行了一个查询,另一个查询将在执行await db.execute_query('UPDATE Data SET Total_Reg = Total_Reg + 1 WHERE rowid = 1')增量查询之前开始执行

我基本上想要的是

顺序如下:

  1. 正在获取使用 data = await db.execute_query('SELECT Total_Reg from Data WHERE rowid = 1')的当前注册数
  2. 检查注册是否已满
  3. 如果没有,则注册用户并通过使用await db.execute_query('UPDATE Data SET Total_Reg = Total_Reg + 1 WHERE rowid = 1')将当前注册数增加1来更新数据库

例如,如果两个用户同时申请注册,那么应该首先注册一个用户,然后只注册另一个用户,并且两个用户的reg_no应该是唯一的

就这样。如何实现此功能?我应该排队吗?或者sqlite中是否有任何功能可以首先获取当前注册表。然后如果值小于max_reg,则将值增加1,并且所有这些都只在一个查询中完成

谢谢


Tags: ofthe用户executedbdataregawait
1条回答
网友
1楼 · 发布于 2024-10-01 00:17:00

可能存在一个SQL解决方案,但是您可以在discord.py的帮助下继续进行

@commands.max_concurrency(1, commands.BucketType.guild, True)
@commands.command() or #@bot.command() depends on what you are using
async def apply(ctx):
    #command here

@commands.max_concurrency(number, bucket_type, wait)用于控制命令的并发性。
number是它可以同时使用的最大次数。
bucket_type是应该检查并发性的地方,如果您希望它是全局使用的话,guild意味着在单个guild中。{
wait是当有人使用该命令而该命令不应运行时它应该做的事情。如果我们将其设置为true,它将等待命令完成运行,如果wait为false,它将引发一个错误,该错误可以通过错误处理程序捕获

如果您只希望一个函数同时执行一次

@commands.command(hidden=True)
@commands.max_concurrency(1, commands.BucketType.guild, True)
async def register(ctx, args):
   #do stuff

然而,人们将能够使用注册

@commands.command()
async def apply(args):
   ctx.command = bot.get_command('register')
   await bot.invoke(ctx)

非常混乱的代码,但应该可以工作

参考资料:

相关问题 更多 >