x=yield f()与x=f()有何不同?

2024-09-30 16:37:07 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在查阅图书馆的资料。我的问题是一般性的,不是针对图书馆的。我想知道的代码是这样的:

class SpiderMiddlewareManager(MiddlewareManager):
    # ...
    def process_start_requests(self, start_requests, spider):
        return self._process_chain('process_start_requests', start_requests, spider)

class
    # ...
    def open_spider(self, spider, start_requests=(), close_if_idle=True):
        # ...
        start_requests = yield self.scraper.spidermw.process_start_requests(start_requests, spider)
        # ...

我的问题是:start_requests = yield self.scraper.spidermw.process_start_requests(...)start_requests = self.scraper.spidermw.process_start_requests(...)有何不同,因为self.scraper.spidermw.process_start_requests已经返回了一个值。如果我的理解是正确的,open_spider不是一个生成器。在

谢谢


Tags: 代码self图书馆defopenscraperrequestsprocess
1条回答
网友
1楼 · 发布于 2024-09-30 16:37:07

你的问题中遗漏了一个重要的细节——你所看到的库是写在^{}之上的,这是一个异步网络框架。完整的方法声明实际上如下所示:

    @defer.inlineCallbacks
    def open_spider(self, spider, start_requests=(), close_if_idle=True):
        assert self.has_capacity(), "No free spider slot when opening %r" % \
            spider.name
        log.msg("Spider opened", spider=spider)
        nextcall = CallLaterOnce(self._next_request, spider)
        scheduler = self.scheduler_cls.from_crawler(self.crawler)
        start_requests = yield self.scraper.spidermw.process_start_requests(start_requests, spider)

^{}修饰符对使用yield的所有调用执行一些魔术。本质上,它允许您编写通常使用回调的异步代码,其方式是看起来是同步的:

inlineCallbacks helps you write Deferred-using code that looks like a regular sequential function. This function uses features of Python 2.5 generators. If you need to be compatible with Python 2.4 or before, use the deferredGenerator function instead, which accomplishes the same thing, but with somewhat more boilerplate. For example:

 @inlineCallBacks    
 def thingummy():
     thing = yield makeSomeRequestResultingInDeferred()
     print thing #the result! hoorj! 

When you call anything that results in a Deferred, you can simply yield it; your generator will automatically be resumed when the Deferred's result is available. The generator will be sent the result of the Deferred with the send method on generators, or if the result was a failure, throw.

Your inlineCallbacks-enabled generator will return a Deferred object, which will result in the return value of the generator (or will fail with a failure object if your generator raises an unhandled exception). Note that you can't use return result to return a value; use returnValue(result) instead. Falling off the end of the generator, or simply using return will cause the Deferred to have a result of None.

如果深入研究process_start_requests调用,您会发现它最终调用scrapy.util.defer.process_chain,它返回一个Deferred

^{pr2}$

相关问题 更多 >