1. 程式人生 > 實用技巧 >從 Scrapy 學習模組匯入技巧

從 Scrapy 學習模組匯入技巧

我們平時匯入第三方模組的時候,一般使用的是import關鍵字,例如:

import scrapy
from scrapy.spider import Spider

但是如果各位同學看過 Scrapy 的settings.py檔案,就會發現裡面會通過字串的方式來指定 pipeline 和 middleware,例如:

 DOWNLOADER_MIDDLEWARES = {
     'Test.middlewares.ExceptionRetryMiddleware': 545,
     'Test.middlewares.BOProxyMiddlewareV2': 543,
 }

  SPIDER_MIDDLEWARES 
= { 'Test.middlewares.LoggingRequestMiddleware': 543, }

我們知道,這裡的Test.middlewares.ExceptionRetryMiddleware實際上對應了根目錄下面的Test資料夾裡面的middlewares.py檔案中的ExceptionRetryMiddleware類。那麼 Scrapy 是如何根據這個字串,匯入這個類的呢?

在 Scrapy 原始碼中,我們可以找到相關的程式碼[1]

def load_object(path):
    """Load an object given its absolute object path, and return it.
    object can be a class, function, variable or an instance.
    path ie: 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware'
    
""" try: dot = path.rindex('.') except ValueError: raise ValueError("Error loading object '%s': not a full path" % path) module, name = path[:dot], path[dot+1:] mod = import_module(module) try: obj = getattr(mod, name) except AttributeError:
raise NameError("Module '%s' doesn't define any object named '%s'" % (module, name)) return obj

根據這段程式碼,我們知道,它使用了importlib模組的import_module函式:

  1. 首先根據字串路徑最右側的.把字串路徑分成兩個部分,例如:Test.middlewares.LoggingRequestMiddleware分成Test.middlewaresLoggingRequestMiddleware
  2. 使用import_module匯入左邊的部分
  3. 從左邊部分通過getattr獲得具體的類

現在我們來測試一下。我們建立的測試檔案結構如下圖所示:

其中,pipelines.py檔案的內容如下圖所示:

class Pipeline:
    def __init__(self):
        print('初始化中。。。。')

    def say(self):
        print('說話 。。。。。')

main.py檔案的內容如下圖所示:

from importlib import import_module

path = 'test.pipelines.Pipeline'

dot = path.rindex('.')
module, name = path[:dot], path[dot + 1:]
modu = import_module(module)
obj = getattr(modu,name)

pipeline = obj()
pipeline.say()

執行main.py,可以看到pipelines.py中的Pipeline類被成功執行了,如下圖所示:

參考資料

[1]

相關的程式碼:https://github.com/scrapy/scrapy/blob/master/scrapy/utils/misc.py#L33

轉自:微信公眾號:未聞Code