如何在python循环中使用线程

时间:2016-03-06 20:52:29

标签: python multithreading python-multithreading circuits-framework

我最近发现了Circuits框架,用于在python中构建异步应用程序。我正在构建一个事件驱动的应用程序,这个框架似乎非常适合我的需求。该框架基于组件的概念,组件在收到事件时作出反应。大!!我按照教程编写了一些简单的应用程序,并且在我尝试使用组件执行一些繁重的计算任务之前,每个东西似乎都能正常工作。我知道,框架支持工人,但我不想使用工人。我想要做的是在一个线程中运行每个组件,以便可以并行执行多个组件。该框架似乎通过start方法支持这种模式。

来自Component.py源代码的

def start(self, process=False, link=None):
    """
    Start a new thread or process that invokes this manager's
    ``run()`` method. The invocation of this method returns
    immediately after the task or process has been started.
    """

    if process:
        # Parent<->Child Bridge
        if link is not None:
            from circuits.net.sockets import Pipe
            from circuits.core.bridge import Bridge

            channels = (uuid(),) * 2
            parent, child = Pipe(*channels)
            bridge = Bridge(parent, channel=channels[0]).register(link)

            args = (child,)
        else:
            args = ()
            bridge = None

        self.__process = Process(
            target=self.run, args=args, name=self.name
        )
        self.__process.daemon = True
        self.__process.start()

        return self.__process, bridge
    else:
        self.__thread = Thread(target=self.run, name=self.name)
        self.__thread.daemon = True
        self.__thread.start()

        return self.__thread, None

def join(self):
    if getattr(self, "_thread", None) is not None:
        return self.__thread.join()

    if getattr(self, "_process", None) is not None:
        return self.__process.join()

所以我尝试使用前面显示的startjoin方法实现经典的生产者/消费者应用程序。我希望生产者和消费者在他们自己的线程中运行,主线程一直等到他们完成。

import time
from threading import current_thread
from circuits import Component, Event, Debugger


class go(Event):
    """ go """

class produced(Event):
    """ produced """

class Consumer(Component):

    def started(self, *args):
        print(current_thread())
        print(current_thread().ident)
        print("Comuser started")

    def produced(self, *args):
        print("I am consuming...")

class Producer(Component):

    def started(self, *args):
        print("Producer started")
        print(current_thread().ident)

    def go(self, *args):
        print("gooooooooooo")
        while True:
            self.fire(produced())
            print("Produced element, going to sleep for 1 sec")
            time.sleep(1)

c = Consumer()
c.start()
p = Producer()
p.start()

p.fire(go())

c.join()
p.join()

不幸的是,上面的代码没有按预期工作。应用程序只在主代码执行后退出。我的代码有什么问题?如果您知道以类似方式使用此库的任何示例,您能否通过链接向我提供?

谢谢。

http://pythonhosted.org/circuits/

修改

在詹姆斯回答之后,我尝试了另外几种方法来运行组件,但我仍然无法让它们并行运行。

代码:

c = Consumer()
c.start()
p = Producer()
p.run()
p.fire(go())

输出:

<Thread(Consumer, started daemon 4334432256)>
4334432256
Comuser started
Producer started
140735301485312

看起来应用程序卡住了。然后,我尝试使用一个主应用程序组件来启动其他组件。

代码:

class App(Component):

    def started(self, *args):
        print("App started")
        p.fire(go())

(App() + Debugger()).run()

输出:

Comuser started
Producer started
4461318144
<registered[*] (<Debugger/* 75445:MainThread (queued=0) [S]>, <App/* 75445:MainThread (queued=2) [R]> )>
<started[*] (<App/* 75445:MainThread (queued=1) [R]> )>
App started
gooooooooooo
Produced element, going to sleep for 1 sec
Produced element, going to sleep for 1 sec
Produced element, going to sleep for 1 sec
Produced element, going to sleep for 1 sec
Produced element, going to sleep for 1 sec
Produced element, going to sleep for 1 sec
Produced element, going to sleep for 1 sec
Produced element, going to sleep for 1 sec
Produced element, going to sleep for 1 sec
Produced element, going to sleep for 1 sec
Produced element, going to sleep for 1 sec
Produced element, going to sleep for 1 sec
Produced element, going to sleep for 1 sec
Produced element, going to sleep for 1 sec
^C<signal[*] (2, <frame object at 0x7fe218725fa8> )>
<stopped[*] (<App/* 75445:MainThread (queued=0) [S]> )>

看起来只有制作人正在运行...我希望在输出中看到的内容如下:

Produced...
Consumed...
Produced...
Consumed...

1 个答案:

答案 0 :(得分:2)

这里的电路作者。

不幸的是,你在这里所拥有的是一个&#34; main&#34;调用.run()的组件。这就是说你已经在&#34; thread&#34;中开始了两个组件。模式,但现在没有&#34;主要&#34;运行组件。

如果您在制作人或消费者身上致电.run()并在&#34;线程&#34;中启动另一个模式;你应该得到更多你想要的预期结果。

更新:对于延迟回复感到抱歉,但我相信您已遵循此模式(*基于hello_multi_bridge.py示例):

from os import getpid


from circuits import ipc, Component, Event, Timer


class go(Event):
    """go"""


class produced(Event):
    """produced"""


class Consumer(Component):

    def produced(self, *args):
        print("Consumed {} from {}".format(repr(args), getpid()))


class Producer(Component):

    def init(self):
        self.consumers = [
            Consumer().start(process=True, link=self),
        ]

    def ready(self, *args):
        Timer(1, go(), persist=True).register(self)

    def go(self, *args):
        for process, bridge in self.consumers:
            self.fire(ipc(produced(), bridge.channel))


class App(Component):

    def init(self):
        Producer().register(self)


App().run()

这会产生如下输出:

Consumed () from 68646
Consumed () from 68646
...