【问题标题】:Twisted non-blocking method - how to?扭曲的非阻塞方法 - 如何?
【发布时间】:2012-03-07 19:06:33
【问题描述】:

我的代码如下所示:

... # class Site(Resource)
def render_POST(self,request)
   otherclass.doAssync(request.args)
   print '1'
   return "done" #that returns the HTTP response, always the same.

...

def doAssync(self,msg):
    d = defer.Deferred()
    reactor.callLater(0,self.doStuff,d,msg)
    d.addCallback(self.sucess)

def doStuff(self,d,msg):
    # do some stuff
    time.sleep(2)  #just for example
    d.callback('ok')

def sucess(msg):
    print msg

输出:

1

好的

到目前为止,一切都很好,但是,HTTP 响应(返回“完成”)仅在延迟之后发生(time.sleep(2))。 我可以这么说,因为浏览器会持续“加载”2 秒。

我做错了什么?

【问题讨论】:

  • 找到了一些答案:stackoverflow.com/questions/6759115/…
  • 注意你在哪些线程中使用了 Twisted API——包括 Deferreds,即 d.callback——。这个版本的代码在错误的线程中使用了d.callback。这会导致所有回调在错误的线程中运行,一旦你做的不仅仅是打印结果,这可能会破坏一些东西。

标签: python twisted twisted.web twisted.internet


【解决方案1】:

您做错的是运行阻塞调用 (time.sleep(2)),而 Twisted 期望您只执行非阻塞操作。等不及的事情。因为那里有time.sleep(2),所以当该函数处于休眠状态时,Twisted 不能做任何其他事情。所以它也不能向浏览器发送任何数据。

对于time.sleep(2),您可以将其替换为另一个reactor.callLater 调用。假设您实际上打算将 time.sleep(2) 调用作为其他阻塞操作,那么如何修复它取决于操作。如果您可以以非阻塞方式执行操作,请执行此操作。对于许多此类操作(如数据库交互),Twisted 已经提供了非阻塞替代方案。如果您正在做的事情没有非阻塞接口并且 Twisted 没有替代方案,您可能必须在单独的线程中运行代码(例如使用 twisted.internet.threads.deferToThread),尽管这需要您的代码是实际上是线程安全的。

【讨论】:

  • 那么,他可以用deferToThread(...) 替换reactor.callLater(...) 吗?
  • 如果你做一个 reactor.callInThread(global_function) 并且 global_function 有一个阻塞操作,比如读取一个本地文件并处理它的内容。只要 global_function 正在运行,工厂线程似乎就会受到影响,因为响应明显变慢,你知道为什么吗?
猜你喜欢
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 2013-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-06
相关资源
最近更新 更多