【问题标题】:OOP in python (related to scrapy)python中的OOP(与scrapy有关)
【发布时间】:2016-04-09 22:18:51
【问题描述】:

问题是如何以安全和可维护的方式在对象之间共享数据。

示例: 我已经构建了产生大量蜘蛛的scrapy 应用程序。虽然每个蜘蛛都连接到单独的管道对象,但我需要比较和排序不同管道之间的数据(例如,我需要按不同项目属性排序的输出:价格、日期等),所以我需要一些共享数据区域。这同样适用于蜘蛛本身(例如,我需要计算最大总请求数)。 第一个实现使用类变量在蜘蛛/管道和每个对象的实例变量之间共享数据。

class MyPipeline(object):
max_price = 0

def process_item(self, item, spider):
if item['price'] > max_price : 
 max_price = item['price']

(实际结构更复杂)然后我想到拥有一堆静态不是OOP,下一个解决方案是为每个类拥有私有类数据并用于存储值:

class MyPipelineData:
def __init__(self):
   self.max_price = 0

class SpidersData:
  def __init___(self, total_requests, pipeline_data):
    self.total_requests = total_requests
    self.pipeline_data = pipeline_data #the shared data between pipelines

class MyPipeline(object):
pipeline_data = None

def process_item(self, item, spider):
  if _data is None:  
     _data = spider.data.pipeline_data  #the shared data between pipelines  
  if item['price'] > _data.max_price : 
   _data.max_price = item['price']

 class Spider(scrapy.spider):
 def __init__(self, spider_data):
   self._data = spider_data
  # and the same object of SpiderData is passed to all spiders 

现在我有一个在所有管道之间共享的数据实例(对于蜘蛛也是如此)。我通常对此是否正确?我应该在 python 中应用与在 C++ 中相同的 OOP 方法吗?

【问题讨论】:

    标签: python oop design-patterns architecture


    【解决方案1】:

    据我了解,您提出的方法是保留从每个对象到捕获所有共享数据的共享对象的引用,我认为这非常好,特别是如果您正确命名它以便顾名思义,为了便于阅读,它是共享的。

    另外,您隐藏了共享对象的内部并将它们封装在诸如 process_item() 之类的方法中,我认为这对于可维护性非常重要(因为共享对象内部的更改不必影响任何其他对象)。

    但我不确定您引导(即初始化)此共享对象的方式。你有这两行

    if _data is None:
      _data = ...
    

    这有点令人惊讶。我不太明白 _data 是什么以及它的定义位置。 pipeline_data 也被分配给 None 并且从未分配给其他任何东西,所以我不确定你的意思。

    如果可能的话,我希望看到一个名为 create_spiders() 的函数创建共享对象,然后一个接一个地创建不同的蜘蛛,给它们一个对共享对象的引用。这样逻辑就很清楚了。


    但是,在您希望共享对象成为单例的特殊情况下,我会考虑在您适当命名的某个模块中将其设为静态对象,例如 Globals.py。然后在您的 Spider 代码中,您会看到类似

    import Globals
    
    class SpiderData:
    
    def update(self):
      self.data.price = 200
      Globals.spiders_data_collector.process(self.data)
    

    在模块 Globals 中,您将初始化对象 spiders_data_collector。我认为这需要更少的代码,这对于可维护性也很重要。

    【讨论】:

    • 感谢您的回答。 pipeline_data 是 _data。您认为我需要一个共享数据实例这一事实是否足以使其成为单例?看起来像使用例如创建它的方法来自主控制分支的 create_spiders 更安全。
    猜你喜欢
    • 2010-10-29
    • 2018-03-10
    • 2016-03-19
    • 1970-01-01
    • 2013-05-14
    • 1970-01-01
    • 1970-01-01
    • 2012-05-22
    • 1970-01-01
    相关资源
    最近更新 更多