【问题标题】:Save python queue to a file将python队列保存到文件
【发布时间】:2011-08-04 16:19:11
【问题描述】:

我正在使用 Python Queue cclass 来管理多个工作线程之间共享的任务列表。实际代码非常庞大,我仍在努力使其完全没有错误。有时,工作线程会崩溃,我必须重新启动整个例程。在此过程中,我丢失了所有已排队的任务。有没有办法将队列保存到文件中,这样每当我重新启动进程时,任务列表就会从该文件中预加载?

乍一看,当我获取或将任务放入队列时,我应该同时读取和写入文件。但是,这并没有给我 queue.task_done() 的功能,并且可能不是最优化的解决方案。任何想法将不胜感激。

【问题讨论】:

  • 在您花太多时间编写自己的并行计算框架之前,请检查是否有可以使用的现有框架。例如。 IPython 的并行框架,或 Kamaelia。

标签: python multithreading queue non-volatile


【解决方案1】:

你考虑过pickling your queue吗?

【讨论】:

  • 您是否建议每次对队列进行更改时,都应将其序列化并保存到文件中?对于较大的队列,这可能不是最佳解决方案。
  • 可以肯定。但是您已经处于次优情况下。防止工作线程崩溃,问题变得没有实际意义。
【解决方案2】:

有多种方法可以解决这个问题,包括pickle 模块...

但在我看来,仅写入文件会很简单,每行一行,列中包含您可能要保存的其他属性的队列中的每个元素,例如 task_done

示例:

element1, True
element2, False
...

在python中读取这样格式的文件非常容易,有点像:

for line in file('path/file.ext'):
    name, state = line.split(sep_char)
    #and them insert into the queue...

【讨论】:

  • 这确实是我想到的第一个解决方案。但是我希望找到一个建立在队列类之上的快速实现。内部解决方案要求我擅长多线程和管理共享数据资源。
【解决方案3】:

执行此操作的简单方法是将 AMQP 用于消息队列,并让消息代理为您处理消息。我使用 RabbitMQ 作为具有持久持久队列的消息代理实现了一个类似的系统。当我在只有 512M RAM 和大约一百万条消息的虚拟 Linux 服务器上使用过时的 1.72 服务器版本时,这些消息甚至在 RabbitMQ 服务器软件崩溃后幸存下来。

我这样做的方式是,每种类型的工作人员都使用来自不同队列的消息。如果我需要多个该类型的工作人员,则消息队列会自动循环,如果工作人员无法完成对消息的处理,他们只是不确认它并返回队列。

我写了一个包含大约 80 行代码的小 shim 模块,放在 kombu 前面,后来将其重写为使用 py-amqplib。如果我早先知道haigha,我会使用它,因为它与 AMQP 规范文档非常匹配。

我不推荐 kombu,因为它对于调试来说非常复杂,并且以奇怪的方式偏离了 AMQP 标准。看看haigha,因为即使文档只是 PyPi 上的一个示例代码片段,它也比 kombu 或 amqplib 更好地记录,因为您可以将 AMQP 规范用作您的 haigha 文档。

【讨论】:

    【解决方案4】:

    我可以提供的一个简单选项是将数据库表包装在一个类中并将其用作您的队列。自动增量列会为此创造奇迹(下一个要删除的项目是 ID 最低的项目)。

    class dbQueue:
      init():
        # Pick some random id for this run (or set it to some thing you know).
      put():
        # Insert entry into table
      get():
        # The update .. select combo removes the need for a database that has transactions.
        # If no entries bear your ID:
          # Update the next entry that is not already marked with your ID.
        # Select the entry that matches your ID and return it.
      task_done():
        # Delete the entry with your ID.
    

    根据队列更新的频率,这不会有最佳性能,即使是内存中的 sqlite 数据库也不会像链表结构那样快。另一方面,您可以使用任何可以访问数据库的工具来查看数据库,这样您就可以看到哪个正在进行中。

    【讨论】:

      【解决方案5】:

      实现worker和master之间的握手机制。

      master 有一个任务列表,在将它们放入队列之前,将列表腌制到文件中。 然后将任务插入队列。当工作人员完成后,他会发回一个 ACK​​ 消息。 仅在此时 unpickle 任务列表并删除相应的 id。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-23
        • 1970-01-01
        • 2021-04-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多