Scrapy Item Pipelines 中 Python 集合的线程安全问题(使用 Twisted 实现并发)

Threadsafety question for Python collections in Scrapy Item Pipelines (using Twisted for concurrency)

Scrapy 有一个概念Item Pipelines that concurrently process (via Twisted) items returned from a Scrapy Spider. The following code example is provided for filtering duplicate items (code copied below). How is it that the set can be used safely by concurrent calls to process_item? It seems that Scrapy invokes item pipelines here

from scrapy.exceptions import DropItem

class DuplicatesPipeline:

    def __init__(self):
        self.ids_seen = set()

    def process_item(self, item, spider):
        if item['id'] in self.ids_seen:
            raise DropItem("Duplicate item found: %s" % item)
        else:
            self.ids_seen.add(item['id'])
            return item

Twisted 和 Scrapy 主要是单线程的。它们不是抢占式多线程,而是通过协作式多任务处理来提供并发性。在协作式多任务系统中,没有抢占。这意味着像上面的 process_item 这样的函数是完全安全的,可以假设 self.ids_seen 在它的第一行和倒数第二行之间不会改变。只有这个process_item方法是运行ning。在 process_item 合作放弃控制之前,无法进行其他工作。它通过引发异常或 return 值来实现。发生这种情况时,控制 returns 到它的调用者(或任何最近的 except 处理程序)。然后该代码到达 运行 直到它决定放弃控制,等等。最终控制 return 一直到 Twisted reactor,它通过调用一些应用程序方法来选择另一个事件来服务。然后重复该过程。