我使用twisted.web框架在python中编写应用程序,使用html 5传输视频。
视频通过static.File('pathtovideo').render_GET()
服务器
问题是,只有一个视频可以一次流式传输,因为它会影响整个过程。
无论如何都要使流式同步或非阻止,无论哪个术语都适合。
我尝试使用deferToThread,但仍然限制了这个过程。
这是我目前使用的类,其中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 :(得分:3)
此代码看起来像阻止的部分实际上是Movie.get
调用。
使用_start_stream
来调用deferToThread
是不正确的,因为_start_stream
使用了Twisted API(File
以及File.render_GET
使用的任何内容),并且使用Twisted是非法的除反应堆线程外的API(换句话说,在使用deferToThread
调用的函数中使用它们是非法的。)
幸运的是,您可以删除使用deferToThread
来修复该错误。
要解决Movie.get
阻止您需要找到异步访问数据库的方法的问题。也许使用deferToThread(Movie.get, Movie.id == self.mid)
- 如果实现Movie.get
的数据库库是线程安全的,那就是。
对于它的价值,你也可以通过在资源遍历层次结构中更早地移动数据库查找逻辑来避免render_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
得到一个结果(对于延迟为“fire”,在lingo)并在其上调用正确的方法,例如render_GET
,以产生对请求的响应。