如何在并发运行的函数中一次执行部分代码?
Posted
技术标签:
【中文标题】如何在并发运行的函数中一次执行部分代码?【英文标题】:How can I execute some part of code once at a time in a concurrently running function? 【发布时间】:2021-07-22 03:13:00 【问题描述】:所以,让我简要介绍一下我想要实现的目标。我有一个名为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
函数是被discord触发的,只要有人输入apply
命令,所以可能会出现data = await db.execute_query('SELECT Total_Reg from Data WHERE rowid = 1')
可以同时执行多次的情况,这会导致当时的注册数相同被返回并存储在所有变量的总变量中。
我知道,当已经有连接更新或访问数据库时,sqlite 会锁定数据库,但是一旦执行查询,另一个查询将在执行await db.execute_query('UPDATE Data SET Total_Reg = Total_Reg + 1 WHERE rowid = 1')
增量查询之前自行开始执行。
我想要的基本上是,
这应该是顺序:
-
使用
data = await db.execute_query('SELECT Total_Reg from Data WHERE rowid = 1')
获取当前注册数
检查注册是否已满
如果没有,则注册用户并通过增加当前编号来更新数据库。注册人数为 1,await db.execute_query('UPDATE Data SET Total_Reg = Total_Reg + 1 WHERE rowid = 1')
例如,如果有 2 个用户同时申请注册,则应先注册一个,然后再注册另一个,并且两个用户的 reg_no
应该是唯一的。
所以,就是这样。我怎样才能实现这个功能?我应该使用队列吗?或者sqlite中是否有任何功能可以首先获取当前的reg。然后如果它小于max_reg
则将值增加 1 并且所有这些都在一个查询中?
谢谢!
【问题讨论】:
【参考方案1】:可能存在 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
是应该检查并发性的地方,行会意味着在一个公会中,如果您希望它是全局使用 commands.BucketType.default
。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)
非常混乱的代码,但应该可以工作。
参考资料:
max_concurrency BucketType【讨论】:
我知道了,但是很抱歉我忘了提一些事情,即这个'注册'功能不是由不和谐直接触发的,有一个单独的'应用'功能可以这样做,并且这个' register' 函数是从那个 'apply' 函数调用的。此外,我希望同时执行“应用”函数中的某些代码,但一次只能执行一次“注册”函数。谢谢! 我编辑了问题,以防您想再次查看。 @Shubham,客户端是discord.Bot
实例还是discord.Client
实例?
客户端是discord.Bot
的实例
对这个问题有什么建议或解决方案吗?以上是关于如何在并发运行的函数中一次执行部分代码?的主要内容,如果未能解决你的问题,请参考以下文章