问题
I am currently working on a system that sends webhooks to multiple Discord using dhooks.
This is the function used to call the function which sends the webhooks. The length of webhooks
is 2 and it's a list of lists.
for hook in webhooks:
thread.start_new_thread(send_hook,(hook, embed, tag))
This is the send_hook function:
def send_hook(hook, embed, tag):
embed.set_footer(text="{} x Will".format(hook[0])) <-- This is the part where the error happens
webhook = Webhook(hook[1])
webhook.send(embed=embed)
The error I am getting is, when I set the footer in line 2 of send_hook
, the variable inserted into the embed variable is sometimes sent to the wrong webhooks - almost as if its being over ridden.
As an example:
This is my list webhooks: [["Webhook 1 text", "discordwebhook1"], ["Webhook 2 text", "discordwebhook1"]]
.
What will happen is that in the channel of discordwebhook1
the footer will say "Webhook 1 text", but in the channel of discordwebhoo2
the footer will say "Webhook 1 text" as-well.
I have tried creating a new variable of the embed in the send_hook
function - however this also didn't work (code below).
def send_hook(hook, embed, tag):
new_embed = embed
new_embed.set_footer(text="{} x Will".format(hook[0])) <-- This is the part where the error happens
webhook = Webhook(hook[1])
webhook.send(embed=new_embed)
I appreciate all help!
Thanks
回答1:
How do you get 'embed'? Notice that 'embed' and 'tag' are always passed to every newly created thread, you need to do a deepcopy of each if necessary
from copy import deepcopy
for hook in webhooks:
thread.start_new_thread(send_hook,(hook, deepcopy(embed), tag))
回答2:
You are experiencing a race condition. Two threads have access to the same variable, and they are both modifying the variable. The outcome of your program depends on which one reaches the code that changes the variable first.
There are two possible solutions, depending on how you want the problem to be resolved:
If you don't need all threads to share the same value, or if the object is small and cheap to copy, make a copy of the variable you are passing before you pass it, by passing
deepcopy(embed)
instead ofembed
- see the solution posted by @user1438644 for code.If you want all threads to share the same value, or if it is expensive to make copies of the object, you will need to create a lock with
my_lock = threading.Lock()
, and when you get to the race condition part of your program (i.e., the part that modifies the shared variable), surround it with a context managerwith my_lock:
, which acquires the lock at the start and returns the lock when finished. For example:
import threading
my_lock = threading.Lock()
# your code here
for hook in webhooks:
threading.Thread(send_hook, args=(hook, embed, tag))
# more code here
def send_hook(hook, embed, tag):
# Ensure embed is only changed by one thread at a time
with my_lock:
print("Lock acquired")
embed.set_footer(text="hello world")
webhook = Webhook(hook[1])
webhook.send(embed=embed)
来源:https://stackoverflow.com/questions/58309718/variable-passed-to-multiple-threads-of-the-same-function