You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何停止Python中运行的线程并重新启动?

解决WhatsApp机器人重复解除静音问题

问题背景

开发基于pyautogui的WhatsApp趣味机器人,未使用Selenium(规避WhatsApp频繁代码变更带来的重复开发)。执行!mute命令时会启动unmute线程,定时为用户解除静音;但执行!unmute命令时,若原unmute线程仍在运行,会导致重复解除静音的问题,需要实现终止当前运行线程后再启动新的unmute线程。

解决方案

核心是利用Event对象实现线程的优雅终止,同时维护全局线程引用,在启动新线程前先终止旧线程。

修改要点

  • 重构unmute函数,将一次性休眠改为循环检查终止信号,确保线程能及时响应终止指令
  • 新增全局变量存储当前运行的unmute线程,方便后续追踪和控制
  • 在!mute和!unmute命令的处理逻辑中,先触发终止信号、等待旧线程结束,再启动新线程

修改后的完整代码

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()
current_unmute_thread = None  # 全局变量存储当前unmute线程

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")
    global unmutestoploop
    # 循环检查终止信号,替代一次性sleep
    remaining_time = time34
    while remaining_time > 0 and not unmutestoploop.is_set():
        time.sleep(1)
        remaining_time -= 1
    
    if unmutestoploop.is_set():
        # 线程被终止,直接退出
        unmutestoploop.clear()
        return
    
    # 执行解除静音操作
    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()
    send(f"{name1} si-a luat unmute")

def mute(name, time2, reason="None"):
    global current_unmute_thread
    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}")
        
        # 启动新线程前先终止旧线程
        if current_unmute_thread and current_unmute_thread.is_alive():
            unmutestoploop.set()
            current_unmute_thread.join()
        
        current_unmute_thread = Thread(target=unmute, args=(int(time2), name))
        current_unmute_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, current_unmute_thread
    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)
                    
                    # 终止旧线程
                    if current_unmute_thread and current_unmute_thread.is_alive():
                        unmutestoploop.set()
                        current_unmute_thread.join()
                    
                    # 启动新线程
                    current_unmute_thread = Thread(target=unmute, args=(int(split[2]), split[1]))
                    current_unmute_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()

修正后的最小复现代码

import time
from threading import Thread, Event

unmutestoploop = Event()
current_unmute_thread = None  # 存储当前线程

def unmute(time34=1, name1="test"):
    print(f"{name1} will get unmuted in {time34}s")
    global unmutestoploop
    # 循环检查终止信号
    remaining_time = time34
    while remaining_time > 0 and not unmutestoploop.is_set():
        time.sleep(1)
        remaining_time -= 1
    
    if unmutestoploop.is_set():
        unmutestoploop.clear()
        print(f"{name1}'s unmute thread was stopped")
        return
    
    print(f"{name1} si-a luat unmute")

def mute(name, time2, reason="None"):
    global current_unmute_thread
    # 终止旧线程
    if current_unmute_thread and current_unmute_thread.is_alive():
        unmutestoploop.set()
        current_unmute_thread.join()
    
    current_unmute_thread = Thread(target=unmute, args=(int(time2), "JJ"))
    current_unmute_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:
            # 终止旧线程再启动新线程
            if current_unmute_thread and current_unmute_thread.is_alive():
                unmutestoploop.set()
                current_unmute_thread.join()
            
            current_unmute_thread = Thread(target=unmute, args=(int(1), "Person"))
            current_unmute_thread.start()

内容的提问来源于stack exchange,提问作者Benioriginalul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 18:17:00