在python中暂停和恢复线程

时间:2017-06-14 18:04:47

标签: python multithreading

我需要暂停和恢复线程,这会不断执行某些任务。调用start()时开始执行,不应该中断,并且必须从调用pause()时继续执行。

我该怎么做?

4 个答案:

答案 0 :(得分:6)

请记住,除了IO阻塞操作的情况外,在Pythin中使用线程不会授予您并行处理权限。有关详细信息,请查看thisthis

你不能在Python中任意暂停一个线程(请在进一步阅读之前记住这一点)。我不确定你是否有办法在操作系统级别(例如使用pure-C)。您可以做的是允许线程在您事先考虑的特定点暂停。我会举个例子:

class MyThread(threading.Thread):

    def __init__(self, *args, **kwargs):
        super(MyThread, self).__init__(*args, **kwargs)
        self._event = threading.Event()

    def run(self):
        while True:
            self.foo() # please, implement this.
            self._event.wait()
            self.bar() # please, implement this.
            self._event.wait()
            self.baz() # please, implement this.
            self._event.wait()

    def pause(self):
        self._event.clear()

    def resume(self):
        self._event.set()

这种方法可行但是:

  • 基于我给你的链接,线程通常是一个坏主意。
  • 您必须使用此方法自行编写run方法。这是因为你需要控制你要检查暂停的确切点,这意味着要访问Thread对象(也许你想要创建一个额外的方法而不是调用{{1} })。
  • 前一点清楚地表明你不能随意停顿,但只是当你指定时你可以暂停。避免在暂停点之间进行长时间操作。

编辑我没有测试过这个,但如果你需要多个这样的线程,这可能没有那么多的子类化:

self._event.wait()

这应该允许你通过调用class MyPausableThread(threading.Thread): def __init__(self, group=None, target=None, name=None, args=(), kwargs={}): self._event = threading.Event() if target: args = (self,) + args super(MyPausableThread, self).__init__(group, target, name, args, kwargs) def pause(self): self._event.clear() def resume(self): self._event.set() def _wait_if_paused(self): self._event.wait() 创建一个没有更多子类的自定义线程,并且你的可调用的第一个参数将接收线程对象,你可以从中调用MyPausableThread(target=myfunc).start()你需要暂停检查。

或者甚至更好,如果你想隔离目标访问线程对象:

self._wait_if_paused()

你的目标callable将在第一个参数中接收一个可以这样调用的函数:class MyPausableThread(threading.Thread): def __init__(self, group=None, target=None, name=None, args=(), kwargs={}): self._event = threading.Event() if target: args = ((lambda: self._event.wait()),) + args super(MyPausableThread, self).__init__(group, target, name, args, kwargs) def pause(self): self._event.clear() def resume(self): self._event.set() (前提是目标callable中的第一个param名为pause_checker())。

答案 1 :(得分:1)

您可以通过附加使所有其他线程等待信号的跟踪函数来完成此操作:

import sys
import threading
import contextlib

# needed to enable tracing
if not sys.gettrace():
    sys.settrace(lambda *args: None)

def _thread_frames(thread):
    for thread_id, frame in sys._current_frames().items():
        if thread_id == thread.ident:
            break
    else:
        raise ValueError("No thread found")
    # walk up to the root
    while frame:
        yield frame
        frame = frame.f_back


@contextlib.contextmanager
def thread_paused(thread):
    """ Context manager that pauses a thread for its duration """
    # signal for the thread to wait on
    e = threading.Event()

    for frame in _thread_frames(thread):
        # attach a new temporary trace handler that pauses the thread

        def new(frame, event, arg, old = frame.f_trace):
            e.wait()

            # call the old one, to keep debuggers working
            if old is not None:
                return old(frame, event, arg)
        frame.f_trace = new

    try:
        yield
    finally:
        # wake the other thread
        e.set()

您可以用作:

import time

def run_after_delay(func, delay):
    """ Simple helper spawning a thread that runs a function in the future """
    def wrapped():
        time.sleep(delay)
        func()
    threading.Thread(target=wrapped).start()

main_thread = threading.current_thread()

def interrupt():
    with thread_paused(main_thread):
        print("interrupting")
        time.sleep(2)
        print("done")

run_after_delay(interrupt, 1)
start = time.time()
def actual_time(): return time.time() - start

print("{:.1f} == {:.1f}".format(0.0, actual_time()))
time.sleep(0.5)
print("{:.1f} == {:.1f}".format(0.5, actual_time()))
time.sleep(2)
print("{:.1f} != {:.1f}".format(2.5, actual_time()))

给予

0.0 0.0
0.5 0.5
interrupting
done
2.5 3.0

请注意中断如何导致主线程上的睡眠等待更长的时间

答案 2 :(得分:0)

您可以使用Process库中的psutil类来完成此操作。

示例:

>>> import psutil
>>> pid = 7012
>>> p = psutil.Process(pid)
>>> p.suspend()
>>> p.resume()

查看此答案:https://stackoverflow.com/a/14053933

答案 3 :(得分:0)

while(int(any) < 2000):
             sleep(20)
             print(waiting any...)