我最近发现了Circuits框架,用于在python中构建异步应用程序。我正在构建一个事件驱动的应用程序,这个框架似乎非常适合我的需求。该框架基于组件的概念,组件在收到事件时作出反应。大!!我按照教程编写了一些简单的应用程序,并且在我尝试使用组件执行一些繁重的计算任务之前,每个东西似乎都能正常工作。我知道,框架支持工人,但我不想使用工人。我想要做的是在一个线程中运行每个组件,以便可以并行执行多个组件。该框架似乎通过start
方法支持这种模式。
:
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()
所以我尝试使用前面显示的start
和join
方法实现经典的生产者/消费者应用程序。我希望生产者和消费者在他们自己的线程中运行,主线程一直等到他们完成。
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...
答案 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
...