使用 class 监控数据流并在 python 中以不同的时间间隔将报告打印到两个不同的 windows

Use a class to monitor a data stream and print reports to two different windows at different time intervals in python

我从来没有太多机会使用线程,但我正在从事的项目需要它。对于下面给出的示例,我已经大大简化了我的问题,但我很确定解决更简单问题的方法将帮助我解决更复杂的问题。

也就是说,这是我的缩减案例:我有一个 class,它的工作是监视通过 class 方法访问的传入数据流。我正在计算流中的统计数据。我想将有关传入数据的报告打印到一个终端 window 并以较短的时间间隔打印,并以固定(更长)的时间间隔将摘要报告打印到另一个 window。

下面的这个演示生成数据并将报告打印到同一个 window:我将如何修改它以将单独的报告打印到两个不同的 windows?

from __future__ import division
from random import gauss
import time

class MyStreamMonitor(object):
    def __init__(self):
        self.sum   = 0
        self.count = 0
    @property
    def mu(self):
        return outv = self.sum/self.count
    def generate_values(self):
        while True:
            yield gauss(0,1)
    def monitor(self, report_interval=1):
        start1 = time.time()
        start2 = time.time()
        for x in self.generate_values():
            self.sum   += x
            self.count += 1

            # print this to terminal 1
            if time.time() - start1 > report_interval:
                start1 = time.time()
                print self.count, x 

            # print this to terminal 2
            if time.time() - start2 > 5*report_interval:
                start2 = time.time()
                print self.mu       

if __name__ == '__main__':
    stream = MyStreamMonitor()
    stream.monitor()

一种方法是写入一个文本文件,然后在第二个终端中,尾随文件:

def monitor(self, report_interval=1):
    second = open('report.txt', 'wt')
    start1 = time.time()
    start2 = time.time()
    for x in self.generate_values():
        self.sum   += x
        self.count += 1

        # print this to terminal 1
        if time.time() - start1 > report_interval:
            start1 = time.time()
            print self.count, x 
            second.write('%d, %s\n' % (self.count, x))

        # print this to terminal 2
        if time.time() - start2 > 5*report_interval:
            start2 = time.time()
            print self.mu
            second.write('%s\n', self.mu)       

        second.flush()

然后在第二个终端上:

$ tail -f report.txt

我最终采纳了@reptilicus 的建议,并使用 redis 将其构建为 client/server 应用程序。这是一个最低限度的工作示例:

server.py

from __future__ import division
from random import gauss
import time
import redis

class MyStreamMonitor(object):
    def __init__(self):
        self.sum   = 0
        self.count = 0
        self.r = redis.StrictRedis()
    @property
    def mu(self):
        if self.count >1:
            outv = self.sum/self.count
        else:
            outv = 0
        return outv
    def generate_values(self):
        while True:
            yield gauss(0,1)
    def monitor(self):
        for x in self.generate_values():
            self.sum   += x
            self.count += 1

            # This is the magic here
            self.r.publish('count', self.count)
            self.r.publish('mu', self.mu)

if __name__ == '__main__':
    stream = MyStreamMonitor()
    stream.monitor()

listener.py

import redis
import time
import sys

r = redis.StrictRedis()
channel = sys.argv[1]
interval = float(sys.argv[2])

while True:
    # Resubscribe at each iteration to ensure we are only receiving
    # the newest message
    pubsub = r.pubsub()
    pubsub.subscribe(channel)

    _ = pubsub.listen().next() # the first message is always just a "1"
    message = pubsub.listen().next()

    print message['data']
    time.sleep(interval )

服务器将数据发布到 "count" 和 "mu" 频道。所以要运行这个,首先我们需要打开一个终端并启动服务器:

$ python server.py

然后我们可以为每个要收听的频道打开一个单独的终端,传入我们要收听的频道和睡眠间隔作为参数。

第一航站楼:

$ python listener.py mu 1

第二航站楼:

$ python listener.py count 2

郑重声明:安装 redis 非常轻松,根本不需要任何配置。根据您的需要,installation/configuration 可能更复杂,但至少对于这个玩具示例,我不需要做任何花哨的事情。