1

私はホーム オートメーション ヘルパーを作成しています。これらは基本的にデーモンのような小さな Python アプリケーションです。それらはそれぞれ個別のプロセスとして実行できますが、作成されるので、それぞれのスレッドで各デーモンを生成し、将来スレッドが死んでも動作できるようにする小さなディスパッチャを作成することにしました。

これは次のようになります (2 つのクラスで作業):

from daemons import mosquitto_daemon, gtalk_daemon
from threading import Thread

print('Starting daemons')
mq_client = mosquitto_daemon.Client()
gt_client = gtalk_daemon.Client()

print('Starting MQ')
mq = Thread(target=mq_client.run)
mq.start()

print('Starting GT')
gt = Thread(target=gt_client.run)
gt.start()

while mq.isAlive() and gt.isAlive():
    pass
print('something died')

問題は、MQ デーモン (moquitto) が正常に動作し、直接実行する必要があることです。

mq_client = mosquitto_daemon.Client()
mq_client.run()

関連するトピックにヒットするすべてのメッセージを聞いて、そこにハングアップします-まさに私が探しているものです。

ただし、ディスパッチャー内で実行すると、奇妙な動作になります。単一のメッセージを受信した後、動作を停止しますが、スレッドは生きていると報告されます。スレッド Woodoo がなくても問題なく動作することを考えると、私はディスパッチャーで何か間違ったことをしていると思います。

念のため、MQ クライアント コードを引用します。

import mosquitto
import config
import sys
import logging


class Client():
    mc = None

    def __init__(self):
        logging.basicConfig(format=u'%(filename)s:%(lineno)d %(levelname)-8s [%(asctime)s]  %(message)s', level=logging.DEBUG)
        logging.debug('Class initialization...')
        if not Client.mc:
            logging.info('Creating an instance of MQ client...')
            try:
                Client.mc = mosquitto.Mosquitto(config.DEVICE_NAME)
                Client.mc.connect(host=config.MQ_BROKER_ADDRESS)
                logging.debug('Successfully created MQ client...')
                logging.debug('Subscribing to topics...')
                for topic in config.MQ_TOPICS:
                    result, some_number = Client.mc.subscribe(topic, 0)
                    if result == 0:
                        logging.debug('Subscription to topic "%s" successful' % topic)
                    else:
                        logging.error('Failed to subscribe to topic "%s": %s' % (topic, result))
                logging.debug('Settings up callbacks...')
                self.mc.on_message = self.on_message
                logging.info('Finished initialization')
            except Exception as e:
                logging.critical('Failed to complete creating MQ client: %s' % e.message)
                self.mc = None
        else:
            logging.critical('Instance of MQ Client exists - passing...')
            sys.exit(status=1)

    def run(self):
        self.mc.loop_forever()

    def on_message(self, mosq, obj, msg):
        print('meesage!!111')
        logging.info('Message received on topic %s: %s' % (msg.topic, msg.payload))
4

2 に答える 2

2

Thread別のクラス インスタンスのメソッドを渡しrunています...どうすればよいかわかりません。

threading.Threadrun2 つの一般的な方法で使用できます。スレッドでラップされた独立した関数を生成するか、メソッドを持つクラスの基本クラスとして使用します。あなたの場合、Clientクラスにはrunメソッドがあるため、ベースクラスが進むべき道のように見えます。

MQクラスで以下を置き換えると、動作するはずです。

from threading import Thread

class Client(Thread):
    mc = None

    def __init__(self):
        Thread.__init__(self) # initialize the Thread instance
        ...
    ...

    def stop(self):
        # some sort of command to stop mc
        self.mc.stop() # not sure what the actual command is, if one exists at all...

次に、それを呼び出すときは、なしで実行しますThread:

mq_client = mosquitto_daemon.Client()
mq_client.start() 

print 'Print this line to be sure we get here after starting the thread loop...'
于 2013-02-12T20:01:43.907 に答える
1

考慮すべきいくつかの事項:

  1. zeromq は、あるスレッドで初期化され、別のスレッドで実行されることを嫌います。提案されているように Client() を書き直してスレッドにするか、クライアントを作成してその関数をスレッドで実行する独自の関数を作成できます。

  2. Client() には、クラス レベルの変数 mc があります。mosquitto_daemon と gtalk_daemon はどちらも同じ Client を使用しているため、Client.mc が勝つかどうかで競合していると思います。

  3. 「while mq.isAlive() and gt.isAlive(): pass」は、スリープせずに何度も何度もポーリングを続けるため、プロセッサ全体を消費します。Python が準スレッド化されているだけであることを考慮すると (Global Interpreter Lock (GIL) では、一度に実行できるスレッドは 1 つだけです)、これは「デーモン」を失速させます。

  4. また、GIL を考慮すると、元のデーモン実装のパフォーマンスが向上する可能性があります。

于 2013-02-12T20:15:18.047 に答える