多线程的一点问题

2022-02-19 17:03:19 +08:00
 123abcdf11345
def isRunning(process_name): 
        try:
            process=len(os.popen('tasklist | findstr '+process_name).readlines())
            if process >=1 :
                return True
            else:
                return False
        except:
            print("程序错误")
            return False

def task_killer():
        while 1:
            if isRunning('Taskmgr.exe'):
                os.system('taskkill /IM Taskmgr.exe')
            time.sleep(1)

以上代码用来干掉 Taskmgr.exe 进程,使用 Threading 模块的 Thread 实现多线程

t1 = threading.Thread(target=task_killer)
t1.start()

现在想问怎么终止这个线程,t1.join 没用,还会堵塞,t1.join(1)也没用,google 找了以下代码也没用

def _async_raise(tid, exctype):
    """raises the exception, performs cleanup if needed"""
    tid = ctypes.c_long(tid)
    if not inspect.isclass(exctype):
        exctype = type(exctype)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
    if res == 0:
        raise ValueError("invalid thread id")
    elif res != 1:
        # """if it returns a number greater than one, you're in trouble,
        # and you should call it again with exc=NULL to revert the effect"""
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")
 
def stop_thread(thread):
    '''强制关闭某一个线程'''
    _async_raise(thread.ident, SystemExit)

谢谢!

3648 次点击
所在节点    Python
12 条回复
BrettD
2022-02-19 17:40:45 +08:00
你在线程里面死循环,join 当然会阻塞了
ClericPy
2022-02-19 18:06:23 +08:00
因为用的 OS thread 基本没有太粗暴的外部 kill 方式 (这也是我喜欢协程的原因, 虽然协程很多时候比线程费劲太多. 有时候真想外部 kill 就用进程当线程也可以)

早年间 Google 上搜 how to kill thread python 一大把原因和各种花哨操作实际并没什么卵用

所以只能线程内部自己结束标识或者设置守护线程什么的
ho121
2022-02-19 20:53:59 +08:00
zhttp
2022-02-19 22:05:12 +08:00
这种一般是弄个标志吧,每次循环检查一下。
ysc3839
2022-02-19 22:50:08 +08:00
怀疑是 X-Y Problem https://coolshell.cn/articles/10804.html
为什么要 kill taskmgr.exe ?为什么杀进程还用调用命令行工具这么低级的方法,不直接调用 API ?为什么要从外部终止这个线程?用个变量让线程自己停止不行吗?
beastk
2022-02-20 00:06:27 +08:00
没什么好办法,试试 func_timeout 吧,超时就退出,注意会增加近一半多的线程
hallDrawnel
2022-02-20 00:24:59 +08:00
python 的多线程就是这么难搞。我自己的小项目直接放弃,用多进程,然后就可以很舒适的中断了。
haoliang
2022-02-20 01:07:15 +08:00
可以用 threading.Event 来做。 我来给个具体示例,通过 ctrl-c 触发 signal interrupt 退出程序。

这事看不出 python 的多线程难搞;没有提供主动终止线程的原因,我想有这个原因:线程与同进程的其他线程共享资源,如果不能做 cleanup 就被终止,会出现 fd 泄漏之类的问题; 而进程不同,操作系统会兜底

```
#!/usr/bin/env python3

import signal
import time
from threading import Event, Thread


def killer(stop: Event):
while True:
if stop.is_set():
print("killer: canceled")
break
print("killer: working")
time.sleep(1)


def main():
stop = Event()

def handle_sigint(*args):
stop.set()

signal.signal(signal.SIGINT, handle_sigint)

th = Thread(target=killer, args=[stop])
th.start()
th.join()

print("main thread exiting")


if __name__ == "__main__":
main()
```
yingxiangyu
2022-02-20 01:42:10 +08:00
换进程,如果出现 pickle 报错,就用 pathos import pathos

Process = pathos.helpers.mp.Process
yolee599
2022-02-20 16:33:00 +08:00
task_killer 里不要 while(1),要 while (quit_flag),你要结束线程的时候先置 quit_flag 为 0 ,再 join
009694
2022-02-21 08:43:38 +08:00
从外部去 kill 一个毫无准备的线程 这本来就是很邪恶的做法。。为什么要提供这种机制 就是为了防止又菜又爱钻空子的人去用 最后变成很多人都在用
18870715400
2022-02-23 17:06:49 +08:00
你的 while 1 没有退出的标志肯定会一直执行下去的呀。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/835055

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX