我有一些 Tornado 的协程相关问题。
有一些python-model A ,它具有执行某些功能的能力。可以从模型外部设置该功能。我不能改变模型本身,但我可以传递任何我想要的功能。我试图通过我的功能教它与Tornado的ioloop一起工作,但我不能。
以下是摘录:
import functools
import pprint
from tornado import gen
from tornado import ioloop
class A:
f = None
def execute(self):
return self.f()
pass
@gen.coroutine
def genlist():
raise gen.Return(range(1, 10))
@gen.coroutine
def some_work():
a = A()
a.f = functools.partial(
ioloop.IOLoop.instance().run_sync,
lambda: genlist())
print "a.f set"
raise gen.Return(a)
@gen.coroutine
def main():
a = yield some_work()
retval = a.execute()
raise gen.Return(retval)
if __name__ == "__main__":
pprint.pprint(ioloop.IOLoop.current().run_sync(main))
所以问题是我将函数设置在代码的一部分中,但是使用模型的方法在另一部分中执行它。
现在,Tornado 4.2.1给了我“ IOLoop已经在运行”,但在Tornado 3.1.1中它可行(但我不知道究竟是怎样)。
我知道接下来的事情:
另外,我不能使用 a.execute()的结果作为未来对象,因为可以从代码的其他部分调用a.execute(),即它应该返回列表实例
所以,我的问题是:有没有机会使用当前的IOLoop从同步模型的方法执行异步genlist
?
答案 0 :(得分:2)
您无法在此处重启外部IOLoop。您有三种选择:
a.execute()
以及堆栈顶部的所有内容更改为协同程序。这是基于Tornado的应用程序的常用模式;试图跨越同步和异步世界是困难的,最好留在一边或另一边。run_sync()
使用IOLoop
。这就是Tornado的同步tornado.httpclient.HTTPClient
所做的事情,这使得从另一个IOLoop
内进行调用变得安全。但是,如果你这样做,外部IOLoop仍然被阻止,所以你没有通过使genlist
异步获得任何东西。在一个单独的线程上运行a.execute
并回调主内部函数的主IOLoop线程。如果a.execute
无法异步,这是避免在IOLoop运行时阻止它的唯一方法。
executor = concurrent.futures.ThreadPoolExecutor(8)
@gen.coroutine
def some_work():
a = A()
def adapter():
# Convert the thread-unsafe tornado.concurrent.Future
# to a thread-safe concurrent.futures.Future.
# Note that everything including chain_future must happen
# on the IOLoop thread.
future = concurrent.futures.Future()
ioloop.IOLoop.instance().add_callback(
lambda: tornado.concurrent.chain_future(
genlist(), future)
return future.result()
a.f = adapter
print "a.f set"
raise gen.Return(a)
@gen.coroutine
def main():
a = yield some_work()
retval = yield executor.submit(a.execute)
raise gen.Return(retval)
答案 1 :(得分:0)
说,你的功能看起来像这样:
module test_register;
//inputs
reg [7:0] D;
reg Clk;
reg Clear;
reg Enable;
//outputs
reg [7:0] OutNum;
//instantiate
Register8bit uut(
.OutNum (OutNum), // <---- added missing output
.D(D),
.Clk(Clk),
.Clear(Clear),
.Enable(Enable)
);
always #50 Clk = ~Clk;
always @(negedge Clk) begin
$display($time, " clr=%b en=%b D=%b OutNum=%b", Clear, Enable, D, OutNum);
end
initial begin
D = 'b10001111; // <---- use 'b
Clk = 1;
#50;
//step 1
#100;
Clear = 0;
Enable = 0;
#100;
//step 2
Clear = 0;
Enable = 1;
#100;
//step 3
Clear = 1;
Enable = 0;
#100;
//step 4
Clear = 1;
Enable = 1;
#100;
//step 5
Clear = 0;
Enable = 1;
#100;
#500 $finish;
end
endmodule
/*
Prints out:
50 clr=x en=x D=10001111 OutNum=xxxxxxxx
150 clr=0 en=0 D=10001111 OutNum=xxxxxxxx
250 clr=0 en=1 D=10001111 OutNum=xxxxxxxx
350 clr=1 en=0 D=10001111 OutNum=10001111
450 clr=1 en=1 D=10001111 OutNum=10001111
550 clr=0 en=1 D=10001111 OutNum=00000000
650 clr=0 en=1 D=10001111 OutNum=10001111
750 clr=0 en=1 D=10001111 OutNum=10001111
850 clr=0 en=1 D=10001111 OutNum=10001111
950 clr=0 en=1 D=10001111 OutNum=10001111
1050 clr=0 en=1 D=10001111 OutNum=10001111
*/
或
@gen.coroutine
def foo():
# does slow things
您可以像这样运行@concurrent.run_on_executor
def bar(i=1):
# does slow things
:
foo()
您可以运行from tornado.ioloop import IOLoop
loop = IOLoop.current()
loop.run_sync(foo)
或任何带有args的协程,如下所示:
bar(..)