2014-04-05 18 views
2

使用twisted.web框架中使用HTML 5扭曲的多个并发或异步流

的视频在服务器的视频流通过static.File('pathtovideo').render_GET() 我写了一个Python应用程序的问题是,只有一段视频一次完成整个流程。

无论如何,要使流异步或非阻塞,无论哪个术语在这里适合。

我试过使用deferToThread,但仍然束缚了这个过程。

这是Im当前正在使用的类,其中Movie是一个ORM表,而mid仅仅是一个任意行的id。

class MovieStream(Resource): 
    isLeaf=True 

    def __init__(self, mid): 
     Resource.__init__(self) 
     self.mid = mid 

    def render_GET(self, request): 
     movie = Movie.get(Movie.id == self.mid) 
     if movie: 
      defered = deferToThread(self._start_stream, path=movie.source), request=request) 
      defered.addCallback(self._finish_stream, request) 
      return NOT_DONE_YET 
     else: 
      return NoResource() 
` 
    def _start_stream(self, path, request): 
     stream = File(path) 
     return stream.render_GET(request) 

    def _finish_stream(self, ret, request): 
     request.finish() 
+0

这个问题的前提是不正确的。试试http://sscce.org/ –

回答

3

看起来像它阻塞的代码部分实际上是Movie.get调用。

这是不正确的调用_start_streamdeferToThread因为_start_stream使用双绞线的API(File和任何File.render_GET用途),它是非法的使用双绞线的API除了在反应器线程(换句话说,它是非法的使用它们功能可拨打deferToThread)。

幸运的是,您可以删除使用deferToThread来修复该错误。

要修复Movie.get块的问题,您需要找到一种异步访问数据库的方法。也许使用deferToThread(Movie.get, Movie.id == self.mid) - 如果实现Movie.get的数据库库是线程安全的,那就是。

通过在资源遍历层次结构中提前移动数据库查找逻辑,您可以避免使用hijinx。

例如,我想你的网址看起来像/foo/bar/<movie id>。在这种情况下,/foo/bar的资源被要求提供<movie id>子女。如果您实现查找这样的:

from twisted.web.resource import Resource 
from twisted.web.util import DeferredResource 

class MovieContainer(Resource): 
    def getChild(self, movieIdentifier): 
     condition = (Movie.id == movieIdentifier) 
     getting = deferToThread(Movie.get, condition) 
     return DeferredResource(getting) 

(这里假设Movie.get是线程安全的),那么你就基本完成。

资源遍历将与DeferredResource(getting)和时呈现对象将需要等待getting有一个结果(对于推迟到“火”,在行话)护理构造的对象,并调用正确的结论方法,例如render_GET,以产生对请求的响应。

+0

这看起来很完美!我从来没有发现延期资源...非常感谢你,我会让你知道它是如何发展的 – user3501657