• 从 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

  • 相关阅读:
    java.lang.IllegalArgumentException: node to traverse cannot be null!
    c3p0连接池的使用
    eclipse插件
    eclipse字体颜色设置
    oracle增删改查
    resultMap / resultType
    oracle 序列 ,check约束
    JSP:一种服务器端动态页面技术的组件规范。
    js
    字体
  • 原文地址:https://www.cnblogs.com/tjp40922/p/14057086.html
Copyright © 2020-2023  润新知