扭曲的线程......如何正确使用它们?

时间:2010-02-11 08:58:04

标签: python multithreading twisted timedelay

我需要编写一个运行两个线程的简单应用程序: - 线程1:在定时时段运行,假设每1分钟一次 - 线程2:只是一个'正常'而真正的循环'做'东西'

如果没有按时间间隔运行的要求我根本不会看到扭曲,但是简单的睡眠(60)不够好并且构造如下:

l = task.LoopingCall(timed_thread)
l.start(60.0)
reactor.run()

看起来很容易实现我想要的目标。

现在,我如何'正确'添加另一个线程?

我在这里看到两个选项:

  • 使用线程库并运行两个'python threads'执行我的while循环,另一个运行reactor.run()。但谷歌似乎反对这种方法并建议使用扭曲线程
  • 使用扭曲的螺纹。这就是我尝试过的,但不知怎的,这对我来说有点笨拙。

以下是我提出的建议:

def timed_thread():
    print 'i will be called every 1 minute'
    return

def normal_thread():
    print 'this is a normal thread'
    time.sleep(30)
    return

l = task.LoopingCall(timed_thread)
l.start(60.0)
reactor.callInThread(normal_thread)
reactor.run()

这似乎有效,但是!我无法阻止该应用。如果我按^ C它将不会做任何事情(没有'callInThread'它只是停止,因为你期望它)。 ^ Z炸弹到shell,如果我然后'杀死%1'它似乎杀死进程(shell报告),但'正常'线程继续运行。杀死PID不会摆脱它,唯一的治疗方法是杀死-9。真奇怪。

因此。我究竟做错了什么?在扭曲中实现两个线程是否正确?我不应该打扰吗?还有哪些“标准”替代方案可以实现定时呼叫? ('标准'我的意思是我可以easy_install或yum安装它们,我不想开始下载并使用随机网页中的一些随机脚本)。

2 个答案:

答案 0 :(得分:5)

你没有在这里解释为什么你真的需要线程。如果你有,我可能已经能够解释为什么你需要它们。 ;)

除此之外,我可以确认您对事物的基本理解是正确的。但是,我可以理解的一个可能的误解是“python线程”和“扭曲线程”彼此不同的概念。他们不是。 Python提供了一个线程库。所有Twisted的线程API都是根据Python的线程库实现的。只有API不同。

关于关机,你有两个选择。

  • 直接使用Python的线程API启动永不运行的线程,并使该线程成为守护进程。即使守护程序线程仍在运行,您的进程也可以退出。此解决方案可能存在的问题是某些版本的Python存在守护程序线程问题,这会导致关闭时崩溃。
  • 使用Twisted的API或stdlib线程API创建线程,但也使用reactor.addSystemEventTrigger('before', 'shutdown', f)添加Twisted关闭钩子。在该钩子中,与工作线程通信并告诉它关闭。例如,您可以在Twisted线程和工作线程之间共享threading.Event并使用钩子set。工作线程可以定期检查它是否已经设置,并在它注意到它时已经退出。除了不崩溃之外,这还提供了另一个优于守护程序线程的优势 - 它允许您在进程退出之前在工作线程中运行一些清理或终结代码。

答案 1 :(得分:2)

假设你的主要是相对无阻塞的:

import random
from twisted.internet import task

class MyProcess:
  def __init__(self):
    self.stats = []
    self.lp = None
  def myloopingCall(self):
    print "I have %s stats" % len(self.stats)
  def myMainFunction(self,reactor):
    self.stats.append(random.random())
    reactor.callLater(0,self.myMainFunction,reactor)
  def start(self,reactor):
    self.lp = task.LoopingCall(self.myloopingCall)
    self.lp.start(2)
    reactor.callLater(0,self.myMainFunction,reactor)
  def stop(self):
    if self.lp is not None:
      self.lp.stop()
    print "I'm done"

if __name__ == '__main__':
  myproc = MyProcess()
  from twisted.internet import reactor
  reactor.callWhenRunning(myproc.start,reactor)
  reactor.addSystemEventTrigger('during','shutdown',myproc.stop)
  reactor.callLater(10,reactor.stop)
  reactor.run()
$ python bleh.py
I have 0 stats
I have 33375 stats
I have 66786 stats
I have 100254 stats
I have 133625 stats
I'm done