python एकाधिक अनुरोधों में उपयोग करने के लिए कुंजी के लिए async क्वेरी डेटाबेस




database asynchronous (2)

मैं चाबियों के लिए डेटाबेस को एसिंक्रोनस से क्वेरी करना चाहता हूं, फिर प्रत्येक कुंजी के लिए कई यूआरएल के लिए अनुरोध करना चाहता हूँ।

मेरे पास एक फ़ंक्शन है जो डेटाबेस से Deferred लौटाता है जिसका मान कई अनुरोधों के लिए महत्वपूर्ण है। आदर्श रूप से, मैं इस फ़ंक्शन को कॉल करता हूं और start_requests से start_requests जनरेटर को वापस start_requests

@inlineCallbacks
def get_request_deferred(self):

   d = yield engine.execute(select([table])) # async
   d.addCallback(make_url)
   d.addCallback(Request)
   return d

def start_requests(self):
    ????

लेकिन इसे कई तरीकों से उठाते हुए उठाते हैं

builtins.AttributeError: 'Deferred' object has no attribute 'dont_filter'

जिसका अर्थ मुझे लगता है कि start_requests को ऑब्जेक्ट्स को लौटाना होगा, डिफर्ड नहीं होना चाहिए, जिनके मान हैं Request ऑब्जेक्ट्स मकड़ी मिडलवेयर की process_start_requests() समान ही लगता है

वैकल्पिक रूप से, मैं शुरुआती अनुरोधों को, कहते हैं, http://localhost/ और उन्हें वास्तविक यूआरएल में बदल सकते हैं, जब कुंजी डाउनलोडर मिडलवेयर के process_request() के माध्यम से डेटाबेस से उपलब्ध है। हालांकि, process_request केवल एक Request ऑब्जेक्ट देता है; यह चाबी का उपयोग करके एकाधिक पृष्ठों पर अनुरोध नहीं प्राप्त कर सकता है: yield Request(url) उठाता है

AssertionError: Middleware myDownloaderMiddleware.process_request
must return None, Response or Request, got generator

इसका सबसे साफ समाधान क्या है

  • डेटाबेस से एसिंक्रोनस की कुंजी प्राप्त करें
  • प्रत्येक कुंजी के लिए, कई अनुरोध उत्पन्न करते हैं

आप डिफर्ड ऑब्जेक्ट के लिए कॉलबैक यूआरएल को किसी प्रकार के जनरेटर के पास दे सकते हैं। जनरेटर तब किसी भी प्राप्त यूआरएल को स्कैरी अनुरोध ऑब्जेक्ट में परिवर्तित करेगा और उन्हें उपज देगा। नीचे आपके द्वारा लिंक किए गए कोड का उपयोग करने वाला एक उदाहरण है (परीक्षण नहीं किया गया):

import scrapy
from Queue import Queue
from pdb import set_trace as st
from twisted.internet.defer import Deferred, inlineCallbacks


class ExampleSpider(scrapy.Spider):
    name = 'example'

    def __init__(self):
        self.urls = Queue()
        self.stop = False
        self.requests = request_generator()
        self.deferred = deferred_generator()

    def deferred_generator(self):
        d = Deferred()
        d.addCallback(self.deferred_callback)
        yield d

    def request_generator(self):
        while not self.stop:
            url = self.urls.get()
            yield scrapy.Request(url=url, callback=self.parse)

    def start_requests(self):
        return self.requests.next()

    def parse(self, response):
        st()

        # when you need to parse the next url from the callback
        yield self.requests.next()

    @static_method
    def deferred_callback(url):
        self.urls.put(url)
        if no_more_urls():
            self.stop = True

जब आपका काम पूरा हो जाए तो अनुरोध जनरेटर को रोकना न भूलें।


एसिंक डेटाबेस क्वेरीज़ के लिए आपने कोई आवश्यकता नहीं दी है। मैं मान रहा हूँ कि आप अपने यूआरएल को स्क्रैप नहीं करना शुरू कर सकते हैं जब तक कि आप डेटाबेस को पहले पूछें न? यदि यह मामला है तो आप केवल क्वेरी को सिंक्रोनस से बेहतर कर रहे हैं, क्वेरी परिणामों पर पुनरावृत्त करें, आपको जो जरूरत है उसे निकालें, फिर ऑब्जेक्ट Request करें। यह डीब्यू एसिंक्रोनस से क्वेरी करने के लिए थोड़ा सा समझ में आता है और बस क्वेरी को पूरा करने के लिए प्रतीक्षा कर रहा है।





twisted