如何停止一个正在运行的线程?

huangapple go评论59阅读模式
英文:

How to stop a running thread?

问题

在第124行,您启动了一个用于计时解除静音的线程,但您还有一个用于解除静音的命令,在第203行更改了解除静音的计时器。如果线程正在运行,您可以停止它,然后在第203行重新启动它。以下是如何实现的示例代码:

import time
from threading import Thread, Event

unmutestoploop = Event()
thread = None  # 用于存储计时解除静音的线程

def unmute(time34=1, name1="test"):
    print(f"{name1}将在{time34}秒后解除静音")
    time.sleep(time34)
    global unmutestoploop
    unmutestoploop.set()
    unmutestoploop.clear()
    print(f"{name1}已解除静音")

def mute(name, time2, reason="None"):
    global thread
    if thread and thread.is_alive():
        # 如果线程正在运行,首先停止它
        thread.join()
    thread = Thread(target=unmute, args=(int(time2), name))
    thread.start()

while True:
    while not unmutestoploop.is_set():
        time.sleep(1)
        input2 = input("静音还是解除静音?")
        print("while循环正在运行")
        if input2.lower() == "静音":
            mute("JJ", 5)
        else:
            thread = Thread(target=unmute, args=(int(1), "Person"))
            thread.start()

在这个示例中,如果您首先输入“静音”,它会触发静音,然后如果您输入“解除静音”,它会停止先前的解除静音线程,并重新启动一个新的解除静音线程。这样可以确保在执行解除静音之前停止计时器。

英文:
from pyautogui import moveTo, click, rightClick, write, keyDown, keyUp, hotkey, scroll
import pyautogui
import pyperclip
import re
import time
from threading import Thread, Event
import sys
unmutestoploop = Event()
def send(message1):
pyautogui.moveTo(189, 20, 0.1)
pyautogui.click()
pyautogui.moveTo(1000, 960)
pyautogui.click()
mes = re.sub('OpenAI', 'BainBan(Ben)', message1)
mes2 = re.sub('ChatGPT', "Makise Kurisu (MK)", mes)
pyperclip.copy(mes2)
pyautogui.hotkey("ctrl", "v")
pyautogui.keyDown("ENTER")
pyautogui.keyUp("ENTER")
def checkuserperms():
time.sleep(0.2)
pyautogui.moveTo(650, 850)
time.sleep(0.2)
pyautogui.click()
pyautogui.moveTo(1550, 580)
time.sleep(1)
pyautogui.dragTo(1700, 580, 1)
time.sleep(0.2)
pyautogui.hotkey("ctrl", "c")
time.sleep(0.2)
moveTo(1370, 190)
time.sleep(0.2)
pyautogui.click()
copy = pyperclip.paste()
print(copy)
if copy == "40 746 499 232" or copy == "40 740 981 295":
return "yes"
elif "40" not in pyperclip.paste():
send("A aparut o eroare in a iti verifica permisiunile, incearca din nou acum xx")
return "no"
def unmute(time34=1, name1="test"):
send(f"{name1} isi va lua unmute in {time34}s")
time.sleep(time34)
global unmutestoploop
unmutestoploop.set()
time.sleep(3)
moveTo(1000, 200)
time.sleep(0.5)
click()
time.sleep(0.5)
moveTo(1800, 400)
scroll(-600)
time.sleep(0.5)
moveTo(1850, 1000)
click()
time.sleep(0.5)
moveTo(1000, 300)
click()
time.sleep(1)
pyautogui.write(f"{name1}")
time.sleep(1)
moveTo(1000, 350)
time.sleep(0.5)
click()
time.sleep(0.5)
moveTo(1100, 380)
time.sleep(0.5)
click()
time.sleep(2)
moveTo(740, 220)
time.sleep(0.5)
click()
time.sleep(0.5)
moveTo(1370, 190)
time.sleep(0.5)
click()
unmutestoploop.clear()
send(f"{name1} si-a luat unmute")
def mute(name, time2, reason="None"):
if name == "Beni" or name == "B" or name == "Ben" or name == "Beni Noul" or name == "Marius" or name == "Mari" or name == "M" or name == 'Ma' or name ==  "Mar" or name == "Mariu":
send("Scuze, n-ai permisiune pentru a face asta xx")
return
else:
pyautogui.moveTo(689, 877, 0.1)
pyautogui.moveTo(820, 877, 0.1)
pyautogui.click()
time.sleep(0.2)
pyautogui.moveTo(675, 820, 0.1)
moveTo(1000, 200)
time.sleep(1)
click()
moveTo(1800, 400)
time.sleep(1)
scroll(-600)
moveTo(1850, 1000)
time.sleep(1)
click()
time.sleep(0.2)
moveTo(1000, 300)
click()
time.sleep(1)
pyautogui.write(f"{name}")
time.sleep(1)
moveTo(1000, 350)
time.sleep(0.2)
click()
time.sleep(0.2)
moveTo(1100, 450)
time.sleep(0.2)
click()
time.sleep(2)
moveTo(740, 220)
time.sleep(0.2)
click()
time.sleep(0.2)
moveTo(1370, 190)
time.sleep(0.2)
click()
send(f"{name} si-a luat mute pentru {time2}s motiv: {reason}")
global thread
thread = Thread(target=unmute, args=(int(time2), name))
thread.start()
def ask(what):
logo = pyautogui.locateOnScreen('2.png')
print("start")
time.sleep(3)
pyautogui.moveTo(500, 10)
pyautogui.click()
moveTo(100, 170)
click()
pyautogui.moveTo(1000, 930)
pyautogui.click()
pyperclip.copy(what)
pyautogui.hotkey("ctrl", "v")
pyautogui.keyDown("ENTER")
pyautogui.keyUp("ENTER")
time.sleep(10)
try:
x = logo.left + 10
y = logo.top + 10
pyautogui.moveTo(x, y, 0.1)
pyautogui.click()
except AttributeError:
logo = pyautogui.locateOnScreen('copy.png', confidence=0.8)
x = logo.left + 10
y = logo.top + 10
pyautogui.moveTo(x, y, 0.1)
pyautogui.click()
if not bool(pyperclip.paste().strip()):
moveTo(100, 70)
click()
time.sleep(4)
ask()
return
command = "!"
talk = "!talk"
mute1 = "!mute"
unmute1 = "!unmute"
lastmessacommand = False
stop = "!stop"
def runspccmd(lastmessage):
global command, talk, mute1, unmute1, lastmessacommand
if command in lastmessage:
if talk in lastmessage:
lastm = str(lastmessage)
final = lastm.replace('<span>', "")
final1 = final.replace('!talk', "")
final2 = final1.replace('</span>', "")
ask(final2)
send(pyperclip.paste())
elif mute1 in lastmessage:
if checkuserperms() == "no":
print("skj")
send("Scuze, n-ai permisiune pentru a face asta xx")
return
else:
lastm = str(lastmessage)
final = lastm.replace('<span>', "")
final1 = final.replace('!mute', "")
final2 = final1.replace('</span>', "")
split = final2.split(" ", 3)
print(split)
mute(split[1], split[2], split[3])
elif stop in lastmessage:
if checkuserperms() == "yes":
send("Bot oprit ;( Ne mai vedem xx")
sys.exit("Bot oprit")
else:
send("n-ai permisiune sa faci asta xx")
elif unmute1 in lastmessage:
if checkuserperms() == "yes":
try:
lastm = str(lastmessage)
final = lastm.replace('<span>', "")
final1 = final.replace('!unmute', "")
final2 = final1.replace('</span>', "")
split = final2.split(" ", 2)
thread = Thread(target=unmute, args=(int(split[2]), split[1]))
thread.start()
except IndexError:
send("eroare, folosire comanda : !unmute nume timp(in secunde)")
else:
send("n-ai permisiune sa faci asta xx")
else:
send("""Comanda necunoscuta. Comenzi:
!talk intrebare
!mute nume secunde motiv
!unmute nume secunde
!stop""")
def getlastmessage():
lm = pyperclip.paste()
final = lm.replace('<span>', "")
final2 = final.replace('</span>', "")
print(final2)
if "!" in final2:
runspccmd(final2)
pyautogui.moveTo(689, 877, 0.1)
time.sleep(0.2)
pyautogui.rightClick()
time.sleep(0.2)
pyautogui.moveTo(700, 850, 0.1)
pyautogui.click() 
time.sleep(0.2)
pyautogui.keyDown("F2")
time.sleep(0.2)
pyautogui.keyUp("F2")
time.sleep(0.2)
pyautogui.hotkey('ctrl', 'a')
time.sleep(0.2)
pyautogui.hotkey('ctrl', 'c')
time.sleep(0.2)
pyautogui.moveTo(1900, 140,0.1)
pyautogui.click()
while True:
while not unmutestoploop.is_set():
time.sleep(1.2)
pyautogui.moveTo(1000, 600)
pyautogui.scroll(-600)
getlastmessage()

In line 124 I start a thread for a timer unmuting someone, but I also have a command that unmutes, that changes the unmute timer in line 203. How can the thread, if it's running, stop and then I want to start it again at line 203. Help much appreciated it's a bot that just does something based on what commands it receives on whatsapp just a fun project in my free time, I'm not using selenium cuz whatsapp is known for changing their code a lot and I don't want to remake this again.

import time
from threading import Thread, Event
unmutestoploop = Event()
def unmute(time34=1, name1="test"):
print(f"{name1} will get unmuted in {time34}s")
time.sleep(time34)
global unmutestoploop
unmutestoploop.set()
unmutestoploop.clear()
print(f"{name1} si-a luat unmute")
def mute(name, time2, reason="None"):
global thread
thread = Thread(target=unmute, args=(int(time2), "JJ"))
thread.start()
while True:
while not unmutestoploop.is_set():
time.sleep(1)
input2 = input("mute or unmute?")
print("while loop working")
if input2.lower() == "mute":
mute("JJ", 5)
else:
thread = Thread(target=unmute, args=(int(1), "Person"))
thread.start()

here is a minimal reproducible example, basically if you write mute it will get muted. Then if you write unmute as if to unmute the person he gets unmuted, but then the person is unmuted again if you wrote mute first time.

答案1

得分: 1

在一般情况下,规范的答案应该是在某个取消事件上使用event.wait,而不是time.sleep,但我建议考虑在这里使用sched

import sched
import time
import threading

class Mutes:

    def sched_thread(self):
        self.scheduler = sched.scheduler()
        self.scheduler.enter(1, 0, self.keepalive)
        self.scheduler.run()

    def __init__(self):
        self.mutes = {}
        self.scheduler = None
        self.schedthd = threading.Thread(target=self.sched_thread)
        self.schedthd.start()
        self._shutdown = False

    def keepalive(self):
        print("pulse")
        if not self._shutdown:
            self.scheduler.enter(5, 0, self.keepalive)  # 保持调度器活动

    def add_mute(self, name, mutetime=5):
        print("muting", name)
        self.mutes[name] = self.scheduler.enter(mutetime, 0, lambda: self.remove_mute(name))

    def remove_mute(self, name):
        print("unmuting", name)
        try:
            self.scheduler.cancel(self.mutes[name])
        except (KeyError, ValueError):
            pass  # 不是早期取消,或者一开始没有静音。

    def shutdown(self):
        self._shutdown = True
        for mute in self.mutes.values():
            try:
                self.scheduler.cancel(mute)
            except ValueError:
                pass  # 可能不必要,用于线程。
        self.schedthd.join()

mutelist = Mutes()
mutelist.add_mute("Jimmy")
mutelist.add_mute("Sam")
mutelist.remove_mute("Jimmy")
time.sleep(10)
print("Entering Shutdown")
mutelist.shutdown()
print("Done")

请注意,我已经将代码中的HTML实体字符(如")替换为正常的双引号。

英文:

In general, the canonical answer would be to event.wait on some cancel event instead of time.sleep, but I'd recommend considering sched here:

import sched
import time
import threading
class Mutes:
def sched_thread(self):
self.scheduler = sched.scheduler()
self.scheduler.enter(1, 0, self.keepalive)
self.scheduler.run()
def __init__(self):
self.mutes = {}
self.scheduler = None
self.schedthd = threading.Thread(target=self.sched_thread)
self.schedthd.start()
self._shutdown = False
def keepalive(self):
print("pulse")
if not self._shutdown:
self.scheduler.enter(5, 0, self.keepalive)  # Keep scheduler alive
def add_mute(self, name, mutetime=5):
print("muting", name)
self.mutes[name] = self.scheduler.enter(mutetime, 0, lambda: self.remove_mute(name))
def remove_mute(self, name):
print("unmuting", name)
try:
self.scheduler.cancel(self.mutes[name])
except (KeyError, ValueError):
pass  # not an early cancellation, or wasn't muted to begin with.
def shutdown(self):
self._shutdown = True
for mute in self.mutes.values():
try:
self.scheduler.cancel(mute)
except ValueError:
pass  # probably unnecessary, for threading.
self.schedthd.join()
mutelist = Mutes()
mutelist.add_mute("Jimmy")
mutelist.add_mute("Sam")
mutelist.remove_mute("Jimmy")
time.sleep(10)
print("Entering Shutdown")
mutelist.shutdown()
print("Done")

huangapple
  • 本文由 发表于 2023年6月26日 00:49:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76551497.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定