9

2つのスレッドを実行する単純なアプリを作成する必要があります。-スレッド1:一定の期間で実行されます。たとえば、1分ごとに実行されます。

時間間隔で実行する必要がなければ、ツイストはまったく見ていなかったでしょうが、単純なsleep(60)は十分ではなく、次のような構造になっています。

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

私がそこで望んでいたことを達成するために本当に簡単に見えました。

では、どうすれば「適切に」別のスレッドを追加できますか?

ここに2つのオプションがあります。

  • スレッドライブラリを使用して、2つの「pythonスレッド」を実行します。1つはwhileループを実行し、もう1つはreactor.run()を実行します。しかし、Googleはこのアプローチに反対しているようで、ツイストスレッディングの使用を提案しています
  • ツイストスレッドを使用します。それは私が試したことですが、どういうわけかこれは私には少し不器用に見えます。

これが私が思いついたものです:

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がシェルに爆撃し、「kill%1」を実行すると、プロセスが強制終了するように見えます(シェルはそれを報告します)が、「通常の」スレッドは実行を続けます。kill PIDはそれを取り除くことはできず、唯一の治療法はkill-9です。本当に奇妙です。

それで。私は何が間違っているのですか?ツイストで2つのスレッドを実装するのは正しいアプローチですか?ねじれを気にしないでください。時限呼び出しを実装するための他の「標準」の代替手段は何ですか?(「標準」とは、easy_installまたはyum installを実行できることを意味します。ランダムなWebページからランダムなスクリプトをダウンロードして使用し始めたくありません)。

4

2 に答える 2

5

ここで実際にスレッドが必要な理由を説明していません。持っていれば、なぜそれらが必要ないのかを説明できたかもしれません。;)

それはさておき、あなたの物事に対する基本的な理解は正しいと確認できます。ただし、私が解決できる誤解の 1 つとして、「python スレッド」と「Twisted スレッド」はまったく異なるという考えがあります。そうではありません。Python は、スレッド ライブラリを提供します。Twisted のスレッド API はすべて、Python のスレッド ライブラリの観点から実装されています。APIのみが異なります。

シャットダウンに関しては、2 つのオプションがあります。

  • Python のスレッド API を直接使用して永久実行スレッドを開始し、スレッドをデーモンにします。プロセスは、デーモン スレッドがまだ実行中であっても終了できます。このソリューションで考えられる問題は、Python の一部のバージョンでデーモン スレッドに問題があり、シャットダウン時にクラッシュする可能性があることです。
  • Twisted の API または stdlib スレッド化 API を使用してスレッドを作成しますが、 を使用して Twisted シャットダウン フックも追加しreactor.addSystemEventTrigger('before', 'shutdown', f)ます。そのフックで、ワーク スレッドと通信し、シャットダウンするように指示します。たとえばthreading.Event、Twisted スレッドと作業スレッドの間で a を共有し、それをフックsetすることができます。作業スレッドは、設定されているかどうかを定期的に確認し、設定されていることに気付いたときに終了できます。これにより、クラッシュしないこと以外に、デーモン スレッドよりも優れた利点が得られます。プロセスが終了する前に、ワーク スレッドでクリーンアップまたはファイナライズ コードを実行できます。
于 2010-02-11T14:08:01.093 に答える
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
私の統計は0です
私は33375の統計を持っています
私は66786の統計を持っています
私は100254の統計を持っています
私は133625の統計を持っています
私はこれで終わりです
于 2010-02-11T09:21:53.370 に答える