从 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
函数:
- 首先根据字符串路径最右侧的
.
把字符串路径分成两个部分,例如: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
分类:
python技巧
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
2018-11-29 day31 管道 进程池 数据共享