從 Scrapy 學習模組匯入技巧
阿新 • • 發佈:2020-11-29
我們平時匯入第三方模組的時候,一般使用的是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
函式:
- 首先根據字串路徑最右側的
.
把字串路徑分成兩個部分,例如:Test.middlewares.LoggingRequestMiddleware
分成Test.middlewares
和LoggingRequestMiddleware
- 使用
import_module
匯入左邊的部分 - 從左邊部分通過
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