Вопрос о безопасности потоков для Python коллекций в конвейерах элементов Scrapy (с использованием Twisted для параллелизма) - PullRequest
0 голосов
/ 29 мая 2020

Scrapy имеет понятие Item Pipelines , которое одновременно обрабатывает (через Twisted) элементы, возвращенные из Scrapy Spider . Следующий пример кода предназначен для фильтрации повторяющихся элементов (код скопирован ниже). Каким образом set можно безопасно использовать для одновременных вызовов process_item? Похоже, Scrapy вызывает конвейеры элементов здесь .

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

1 Ответ

1 голос
/ 30 мая 2020

Twisted и Scrapy в основном однопоточные. Вместо вытесняющей многопоточности они обеспечивают параллелизм посредством совместной многозадачности. В кооперативной многозадачной системе нет вытеснения. Это означает, что функция, подобная process_item выше, вполне безопасно предположить, что self.ids_seen не изменится между первой и предпоследней строками. Только этот метод process_item работает. Никакая другая работа не может выполняться, пока process_item совместно не откажется от управления. Он делает это, вызывая исключение или возвращая значение. Когда это происходит, управление возвращается вызывающей стороне (или какому-либо другому обработчику except). Затем этот код запускается, пока не решит отказаться от управления, и так далее. В конце концов управление полностью возвращается к Twisted reactor, который выбирает другое событие для обслуживания, вызывая некоторый метод приложения. Затем процесс повторяется.

...