【问题标题】:Kill python thread using os使用 os 杀死 python 线程
【发布时间】:2015-04-22 09:22:09
【问题描述】:

类似的问题我已经问过很多次了,但还是找不到合适的解决方案。

我有一个外部函数,在某些情况下可以运行很长时间。我想在 30 秒后打断它。

我该怎么做?

  1. 线程很好,但我无法阻止它们(我无权访问外部函数的代码)
  2. 多处理也不是一个选项,因为我在 mod_wsgi 下运行站点。

有没有可靠的方法来停止线程? 也许使用 os.system 或 os.kill。如果是,那么如何?

外部函数只执行一些计算,没有网络连接或文件打开。所以,我只需要停止进程并清理即可。

我的代码(实际上取自某个来源):

def time_limit(timeout):
    def internal(function):
        def internal2(*args, **kw):
            class MyThread(threading.Thread):
                def __init__(self):
                    threading.Thread.__init__(self)
                    self.result = None
                    self.error = None

                def run(self):
                    try:
                        self.result = function(*args, **kw) # this is external
                    except Exception as e:
                        self.error = e

                def _stop(self):
                    if self.isAlive():
                        threading.Thread._Thread__stop(self)

            c = MyThread()
            c.start()
            c.join(timeout)
            counter = 0
            if c.isAlive():
                c._stop()
                raise TimeoutException
            if c.error:
                raise c.error
            return c.result
        return internal2
    return internal

【问题讨论】:

    标签: python linux multithreading


    【解决方案1】:

    你不能杀死线程,但你可以杀死一个进程。如果您可以使用进程而不是线程,则可以使用multithreading module。进程可以是来自父应用程序的terminated

    如果您更详细地描述您的任务,也许我可以提供更多帮助。

    【讨论】:

      【解决方案2】:

      不,没有办法从外部停止线程。一个线程完全处于产生它的进程的控制之下,从外部杀死它意味着你必须弄乱进程内存,这通常意味着你使进程功能失调;你通常做的是以某种形式处理消息,允许线程在某些外部脉冲下自行终止。

      【讨论】:

      • 没办法。线程不能被杀死。它是流程的内部事物,没有干净、定义明确的方式与之交互。基本上,您的线程必须愿意自行终止。
      • 这个问题的其他答案呢?你怎么看?
      • @AndrewFount:castaway2000 的答案根本不涉及线程,而是处理。 Noctis 的回答基本上是添加一个点,始终允许您在线程的上下文中调用线程的停止方法,这无异于添加一种让线程自行停止的非常慢的方法。你接受的答案就是我所说的,但是没有信息为什么你不能杀死线程,所以我有点难过你选择了那个。
      • @AndrewFount:你没有真正理解,对不起。
      【解决方案3】:

      您可以使用 os.system 执行终端命令,这将允许您在程序中进行终端控制。如果你想

      import os
      os.system("terminal command goes here")
      

      对于 linux,请阅读以下内容: https://www.digitalocean.com/community/tutorials/how-to-use-ps-kill-and-nice-to-manage-processes-in-linux

      查看pthread_kill() Stack exchange - how to kill a thtread

      对于窗户: http://forum.thewindowsclub.com/windows-tips-tutorials-articles/29463-kill-processes-using-command-prompt-windows-7-8-a.html

      对于 mac: http://www.chriswrites.com/how-to-view-and-kill-processes-using-the-terminal-in-mac-os-x/

      或者:

      import signal
      signum = signal.getsignal(c)
      signal.siginterrupt(signum, flag)
      

      或者:

      import os
      sigID = c.get_ident 
      os.system("kill -SIGKILL " + sigID)
      

      signal doc page 您还可以设置一些定时器功能。

      关于 python 线程的其他信息: https://docs.python.org/2/library/thread.html

      【讨论】:

      【解决方案4】:

      这可能不是终止线程的最佳方法,但this answer 提供了一种终止线程的方法。请注意,您可能还需要实现一种方法,使线程在其代码的关键部分无法被杀死。


      为方便起见,代码和使用示例如下:

      import threading
      import sys
      
      class StopThread(StopIteration): pass
      
      threading.SystemExit = SystemExit, StopThread
      
      class Thread2(threading.Thread):
      
          def stop(self):
              self.__stop = True
      
          def _bootstrap(self):
              if threading._trace_hook is not None:
                  raise ValueError('Cannot run thread with tracing!')
              self.__stop = False
              sys.settrace(self.__trace)
              super()._bootstrap()
      
          def __trace(self, frame, event, arg):
              if self.__stop:
                  raise StopThread()
              return self.__trace
      
      
      class Thread3(threading.Thread):
      
          def _bootstrap(self, stop_thread=False):
              def stop():
                  nonlocal stop_thread
                  stop_thread = True
              self.stop = stop
      
              def tracer(*_):
                  if stop_thread:
                      raise StopThread()
                  return tracer
              sys.settrace(tracer)
              super()._bootstrap()
      
      ################################################################################
      
      import time
      
      def main():
          test = Thread2(target=printer)
          test.start()
          time.sleep(1)
          test.stop()
          test.join()
      
      def printer():
          while True:
              print(time.time() % 1)
              time.sleep(0.1)
      
      if __name__ == '__main__':
          main()
      

      Thread3 类的代码运行速度似乎比 Thread2 类快大约 33%。

      【讨论】:

      • 我看到了那个答案。它下面的代码慢得令人无法接受。
      • @AndrewFount 如果您可以将stop 方法引入Thread 类而不会造成性能损失,请告诉我。我很想看到该问题的最佳跨平台解决方案。
      • 我并不是说,我不能接受一些缓慢,但该代码永远运行。
      • @AndrewFount 你检查this question了吗?答案之一中列出的 ThreadWithExc 类似乎没有任何开销。似乎只需要ctypes 的一点魔法。
      • 这正是现在实现的功能。唉,它并不总是杀死线程。
      猜你喜欢
      • 2011-04-19
      • 1970-01-01
      • 2021-11-13
      • 2022-11-29
      • 2023-02-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-24
      • 2016-07-10
      相关资源
      最近更新 更多