如何将运行函数的输出作为Python中的事件

时间:2014-05-14 05:39:09

标签: python

我对下面发布的示例有疑问......

在我的机器上calcIt()功能大约需要5秒钟才能完成。 从MyClass的callCalcIt()方法内部调用相同的calcIt()函数。 使用while循环MyClass是"观看"用calcIt()函数完成。

问题:calcIt()方法中的while循环仅打印'...running'一次。老实说,我期待至少看到一个无限循环' '...running'每秒打印数千次的行为类型。观察while循环只执行a print '...running'行一次的事实让我相信while循环非常松散地观察{&1;} calcIt()的进展情况。如果是这样,应该使用其他(除了while循环)方法来确保你得到你想要的东西:来自calcIt()函数的即时反馈?

def calcIt():
    a=True
    while a:
        for i in range(25000000):
            pass
        a=False
    return True

class MyClass(object):
    def __init__(self):
        super(MyClass, self).__init__()

    def callCalcIt(self):
        b=True
        while b:
            result=calcIt()
            print '...running'
            if result: b=False

print 0    
calcIt()
print 1

c=MyClass()
c.callCalcIt()
print 2

以后编辑:

发布修订后的代码,其中包含Ebarr建议的解决方案实施:

import threading

updateMe=[]

def calcIt():
    a=True
    while a:
        for y in range(3):
            for i in range(15000000):
                pass
            updateMe.append(1)
        a=False
    return True

class MyClass(object):
    def __init__(self):
        super(MyClass, self).__init__()

    def callCalcIt(self):
        thread = threading.Thread(target=calcIt)   
        thread.start()
        print '\n...thread started'
        while thread.is_alive():
            if len(updateMe)==1: print '...stage 1'
            if len(updateMe)==2: print '...stage 2'
            if len(updateMe)==3: print '...stage 3'

    def printUpdate(self):
        print 'updateMe=', len(updateMe)


c=MyClass()
c.callCalcIt()

3 个答案:

答案 0 :(得分:2)

我不确定你期望发生什么,但解释很简单。您正在运行单线程代码。这意味着以上所有内容都将以串行方式执行,因此代码中的两个while循环之间不会出现并发现象。

您似乎要问的是如何对代码进行处理,以便您可以检查正在运行的函数的进度。如果是这种情况,您可以将calcIt变为线程。

import threading

class CalcIt(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        for i in range(25000000):
            pass

然后,您可以将callCalcIt更改为:

def callCalcIt(self): 
    thread = CalcIt()     
    thread.start()
    while thread.is_alive():
        print '...running'

或者,您可以更简单:

import threading

def calcIt():
    for i in range(25000000):
        pass

def callCalcIt():
    thread = threading.Thread(target=calcIt)
    thread.start()
    while thread.is_alive():
        print '...running'

callCalcIt()

答案 1 :(得分:1)

我可以提出两种方法,但都需要对calcIt函数进行一些修改。

方法1,回调:

def calc_it(callback):
    r = 25000000
    for x in xrange(r+1):
        if not (x % 1000):
            callback(x, r)  # report every 1000 ticks

class Monitor(object):
    def print_status(self, x, r):
        print "Done {0} out of {1}".format(x, r)

    def call(self):
        calc_it(self.print_status)

方法2,生成器:

def calc_it():
    r = 25000000
    for x in xrange(r+1):
        if not (x % 1000):  # report every 1000 ticks
            yield x, r

class Monitor(object):
    def call(self):
        for x, r in calc_it():
            print "Done {0} out of {1}".format(x, r)

(附注:在任何情况下Monitor都不必是一个类,这只是为了与原始代码保持一致。)

答案 2 :(得分:1)

不确定您要完成的是什么,但您可以使用my newly written generator state machine thingie。像这样:

from generatorstate import State

def calcIt():
    while True:
        for i in range(25000000):
            pass
        yield

tick = State(calcIt)
print 0
tick()
print 1
tick()
print 2

我已经添加了几个例子,如果你认为它可能适合,可以偷看一下。