V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
Motorola3
V2EX  ›  Python

Python 怎么优雅的掐死一个子线程?

  •  
  •   Motorola3 · 11 天前 · 2283 次点击
    python 的 threading 包 创建的子线程 真的没办法直接给掐死吗

    我看往上很多封装都是添加标识符 判断标识符

    我的子线程中除了有 while 循环 还有嵌套的 while 循环 和很多 if 导致我现在需要给每个 if 都写一个 and 判断标识符,然后我的线程中还有 sleep 我还得给 sleep 添加 判断

    有没有办法直接掐死呀 我发现 pyhon 创建子线程后会在任务管理器中可以看到 多出来了一个字进程
    有没有办法拿到那个进程 PID 然后调用 Windows 直接给进程杀掉?
    第 1 条附言  ·  10 天前
    看了一下各位大佬们的评论 我大概清楚了
    我的具体需求其实就是 要立马关闭一个内部带有嵌套 带有延时的无限循环

    所以这样的话 我是否可以换一种思路
    原先是我创建一个子线程 在子线程中去执行循环,现在的话我可以将这个循环单独拿出去 比如再做一个.exe 或者是做一个.bat?然后在子线程中去执行他 然后他在执行过程中卡住字线程,当我要关闭的时候 我直接 kell 掉这个进程 这样子线程也可以向下执行就 end 了 不知道是否可行

    但是这样的话会有一个问题,我无法更新我的 pyqt 主窗体文字了,因为我目前是用插槽函数来在子线程中修改主窗体内容的
    26 条回复    2024-04-28 18:15:36 +08:00
    zsj1029
        1
    zsj1029  
       11 天前
    就算可以,就不优雅了吧,建议问问 chatgpt
    gjquoiai
        2
    gjquoiai  
       11 天前
    signal.pthread_kill
    ysc3839
        3
    ysc3839  
       11 天前 via Android
    kill 不“优雅”,而且是有问题的,比如子线程持有 GIL 时被杀死,那就没办法释放了,其他 Python 线程就被锁死了。除此之外还有对象没正常释放内存泄漏等问题。
    nagisaushio
        4
    nagisaushio  
       11 天前
    所有优雅的方法都是协作式的
    Garasu
        5
    Garasu  
       11 天前
    你这个 “掐死” 用的很优雅。2333
    keakon
        6
    keakon  
       11 天前   ❤️ 2
    有一个优雅的办法叫作 PyThreadState_SetAsyncExc ,就是在另一个线程里抛异常……
    LeeReamond
        7
    LeeReamond  
       11 天前
    三种方法
    1. 发信号,问题楼上说了
    2. 发异常,不够优雅,通用性是可以的
    3. 正常程序设计所指明的方法就是你通过任意一种通信方式指明关闭子线程后,子线程自行终止并退出,这才是优雅的
    yanyao233
        8
    yanyao233  
       11 天前 via Android
    “掐死”这个行为本身就不够优雅,我一般会让子线程自杀,“亲,你没用了,可以死了哦~”
    0o0O0o0O0o
        9
    0o0O0o0O0o  
       11 天前
    赞同楼上
    henix
        10
    henix  
       11 天前   ❤️ 1
    月经问题
    [为什么大多数语言的标准库都不提供或不鼓励使用“杀线程”的功能?]( https://www.zhihu.com/question/569168858)
    zictos
        11
    zictos  
       11 天前
    创建子线程并不会多出进程啊,除非创建子进程。
    子进程是可以终止的: https://www.v2ex.com/t/740071
    ClericPy
        12
    ClericPy  
       11 天前
    系统级线程,只能让它自己死,stackoverflow 上讨论好多方案,没几个安全或有效的。后来折中方案就是:threading.Event 之类的,或者每隔一点时间轮询或判断超时,别折腾了

    现在已经改用进程和协程了,前者代码改动很小,IPC 也不麻烦,后者比较看本事,用不好就全家阻塞
    xiangyuecn
        13
    xiangyuecn  
       10 天前
    取个优雅的函数名字,里面封装了一行 kill 代码
    iorilu
        14
    iorilu  
       10 天前
    最好的法子就是弄个 信号变量, 然后主线程修改这个变量, 子线程判断退出

    比如弄个 need_run = True
    nuk
        15
    nuk  
       10 天前
    设计上如果支持 kill safe 就比较方便, 比如 erlang 。
    python 能够在 thread 里处理 signal 并且 raise exception 到这个 thread 的话也可以解决,但是不行因为 signal handler 全部在 main thread 里执行。
    不过 python 其实是可以从其他线程直接 raise exception 到指定的线程的,参考这里 https://gist.github.com/liuw/2407154
    这样就直接用 try 包围一下就行。
    cndenis
        16
    cndenis  
       10 天前
    @nuk erlang 自称微进程, 不叫线程, 微进程间是没有共享内存的. 线程和进程的区别在于是否能共享内存, 可写的共享内存很难做到 kill safe
    kneo
        17
    kneo  
       10 天前 via Android
    问错了。你想问的是“如何粗暴的杀死一个线程”。
    Motorola3
        18
    Motorola3  
    OP
       10 天前
    @iorilu 嗯 这也是我看到最多的方法也是我现在用的
    Motorola3
        19
    Motorola3  
    OP
       10 天前
    @kneo 哈哈哈 是 如何优雅的 粗暴的杀死一个线程
    iorilu
        20
    iorilu  
       10 天前
    @Motorola3 我觉得这就是最好的方法

    因为线程是操作系统控制的, python 不能完全掌控, 程序里有任何地方不能由程序本身控制都可能造成未知风险

    除非没其他办法 , 否则还是通过变量控制, 可以做到程序完全掌控是最好的
    Motorola3
        21
    Motorola3  
    OP
       10 天前
    @iorilu 我有一计
    realJamespond
        22
    realJamespond  
       10 天前
    pthread wait 时发信号唤醒 thread 退出 loop ,如果正在处理 job 就等 job done 时退出
    Motorola3
        23
    Motorola3  
    OP
       10 天前
    @zictos 我是通过 threading 来创建的子线程 不过外面包了一层 pyqt 的 workThreading 然后打包成.exe 后 就会多出来一个 子进程在任务管理器中 难道是 pyqt6 的原因?
    volvo007
        24
    volvo007  
       10 天前
    @yanyao233 “自杀吧 Lancer” 是吧🐶
    zictos
        25
    zictos  
       10 天前
    @Motorola3 #23 可能是 pyqt 创建了子进程吧,子进程的 pid 是容易拿到的,问题是即便杀死了子进程,主进程创建的子"线"程也不会结束
    Maerd
        26
    Maerd  
       5 天前
    你都用 QT 了,多线程操作就使用 QThread 不好么,然后用 QTimer 做轮询,通信用信号和插槽,怎么会影响主窗体更新
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1260 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 17:16 · PVG 01:16 · LAX 10:16 · JFK 13:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.