在执行时中途停止一系列语句

时间:2016-07-18 02:52:39

标签: python multithreading

我创建了一个守护程序线程,它将在主Object启动后独立运行。我可以推送我希望它通过其堆栈运行的各种函数。但我从不希望守护程序线程在堆栈中有超过2个函数(我正在构建的项目的设计选择)。因此,如果一个名为run_this_function的方法正在此线程中运行并且主对象再次将该函数推送到堆栈,那么我想中途停止run_this_function,然后重新启动推送到该线程的新函数。

我的问题是,一旦发起声明,是否有任何方法可以停止一系列声明。

{{app-header}}

上面的代码是我到目前为止所写的。我会创建一个myThread对象并将我想要运行的方法推送到thread_stack。因此,如果我已经运行了一个函数(例如some_function),那么如何在前两个执行语句之后中途停止它。我是否被迫每行都有if语句?

另外,请随意评论/批评我对线程的使用。我还是很新的。谢谢! :)

1 个答案:

答案 0 :(得分:0)

Python有两个线程API:

使用线程创建的主题难以终止或中断。 This SO question详述了该问题的几种解决方法,包括:

  • 让线程定期检查停止条件
  • 在线程中引发异常(来自另一个线程)
  • 重新定义__trace方法

此外,请查看this github gist及其评论 另一种将信号传递给另一个线程的方法。

所有这些方法都有缺点,在某些情况下可能无法正常工作。 特别是,使用threading创建的线程不能被中断 如果他们正在进行系统调用。

使用多处理库创建的线程是真实的 进程并可以接收Unix信号或使用terminate方法终止。 缺点是它们在不同的地址空间中运行 处理信号时必须小心,以确保资源 正确清理。

以下是如何使用多处理执行此操作的示例代码。 运行程序后,输入一个延迟(如3)以添加新作业 队列。如果队列增长超过2,则当前作业将是 杀害。输入延迟0以等待所有作业完成。

#!/usr/bin/env python

from multiprocessing import Process
import Queue
import os
import signal
import threading
import time

class RunJobs():
  def __init__(self):
    self.queue = Queue.Queue()
    self.current_process = None
    pass

  def run_loop(self):
    # intended to be run in 
    while True:
      # atomically get the next job
      job = self.queue.get(True, None)
      if job is None:
        break
      p = Process(target=run_job, args=job)
      self.current_process = p
      p.start()
      p.join()
      self.current_process = None

  def abort(self): # abort the current process
    p = self.current_process
    if p:
      p.terminate()
      # alternatively, use os.kill(p.pid, ...) to send a signal

  def add_job(self, job):
    # atomically add the job calling self.abort()
    # if there are too many jobs on the queue
    # N.B.: For illustrative purposes only. There is
    # a race condition here. To avoid it use locks.
    self.queue.put(job)
    if self.queue.qsize() > 2: self.abort()

def run_job(delay, message):
  for i in xrange(5):
    print  "\n ===", message, "i =", i
    time.sleep(delay)

def main():
  rj = RunJobs()
  t = threading.Thread(target=rj.run_loop)
  t.start()

  i = 1
  while True:
    delay = raw_input("Enter delay for job {}: ".format(i))
    delay = int(delay)
    if delay == 0:
      rj.add_job(None)
      break
    job = ( delay, "job {} - delaying for {}".format(i, delay) )
    rj.add_job(job)
    i += 1
  print "Waiting for all jobs to finish..."
  t.join()

if __name__ == '__main__':
  main()