9

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

如果不是按时间间隔运行的要求,我根本不会看扭曲,但简单的 sleep(60) 还不够好,结构如下:

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

看起来很简单,可以在那里实现我想要的。

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

我在这里看到两个选项:

  • 使用线程库并运行两个“python 线程”,一个执行我的 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,如果我然后执行 'kill %1' 它似乎会杀死进程(shell 报告),但 'normal' 线程继续运行。kill PID 不会摆脱它,唯一的治疗方法是 kill -9。真的很奇怪。

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

4

2 回答 2

5

你没有解释为什么你在这里实际上需要线程。如果你有,我可能能够解释为什么你不需要它们。;)

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

就关机而言,您有两个选择。

  • 直接使用 Python 的线程 API 启动您的永远运行线程,并使该线程成为一个守护进程。即使守护线程仍在运行,您的进程也可以退出。此解决方案的一个可能问题是某些版本的 Python 存在守护线程问题,这将导致在关闭时崩溃。
  • 使用 Twisted 的 API 或 stdlib 线程 API 创建线程,但也使用reactor.addSystemEventTrigger('before', 'shutdown', f). 在那个钩子中,与工作线程通信并告诉它关闭。例如,您可以threading.Event在 Twisted 线程和您的工作线程之间共享一个并使用挂钩set。工作线程可以定期检查是否已设置,并在发现已设置时退出。除了不会崩溃之外,这与守护线程相比还有另一个优势——它可以让您在进程退出之前在工作线程中运行一些清理或终结代码。
于 2010-02-11T14:08:01.093 回答
2

假设您的 main 是相对非阻塞的:

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()
$蟒蛇bleh.py
我有 0 个统计数据
我有 33375 个统计数据
我有 66786 个统计数据
我有 100254 个统计数据
我有 133625 个统计数据
我受够了
于 2010-02-11T09:21:53.370 回答