【问题标题】:Joining concurrent Python Output加入并发 Python 输出
【发布时间】:2011-02-17 21:53:16
【问题描述】:

我正在使用这样的东西:

find folder/ | xargs -n1 -P10 ./logger.py > collab

logger.py 内部,我正在处理输出重新格式化的行的文件。所以协作应该看起来像

{'filename' : 'file1', 'size' : 1000}
{'filename' : 'file1', 'size' : 1000}
{'filename' : 'file1', 'size' : 1000}
{'filename' : 'file1', 'size' : 1000}

相反,有时线条会变得混乱:

{'filename' : 'file1', 'size' : 1000}
{'file
{'filename' : 'file1', 'size' : 1000}
name' : 'file1', 'size' : 1000}
{'filename' : 'file1', 'size' : 1000}

如何防止/纠正这种情况?

【问题讨论】:

  • 你的 logger.py 是多线程的还是什么?
  • @aioobe: xargs -n1 -P10 运行十个并发进程(logger.py)。见xargs
  • 哦,对了,误读了手册页并将其与-p 混淆了。这是个好问题!
  • logger.py 中的输出是如何完成的?
  • @Josh,您是否尝试过在写入后添加flush 或使用无缓冲文件对象? (顺便说一句,这就是格伦在下面建议的)

标签: python bash xargs


【解决方案1】:

一般来说,如果不深入研究多进程锁定,有些问题很难保证这不会发生。但是,您通常可以大大减少问题。

最常见的原因是 Python 或 libc 中的 I/O 缓冲。例如,它可能正在缓冲 16k 的输出,然后一次写入整个块。您可以通过在写入标准输出后刷新标准输出来减少它,但这很尴尬。从理论上讲,您应该能够将-u 传递给Python 以禁用标准输出缓冲,但是当我尝试它时它不起作用。有关更通用的解决方案,请参阅 Sebastjan 对Disable output buffering 的回答(尽管可能有一种方法可以更直接地禁用输出缓冲)。

第二个问题是底层写入并不总是原子的。特别是,对管道的写入仅在一定大小(PIPE_BUF,通常为 512 字节)内是原子的;高于此不能保证。这仅严格适用于管道(而不是文件),但同样适用于一般问题:较小的写入更有可能以原子方式发生。见http://www.opengroup.org/onlinepubs/000095399/functions/write.html

【讨论】:

    【解决方案2】:

    复杂且技术上正确的解决方案是实现一个互斥锁用于写入,但我认为这不是最理想的。

    反正也不好玩。如何将 xargs 的输出通过管道传输(这样您可以获得可靠的输出块,而不是被分解的输出流),然后以某种方式组合这些块?

    【讨论】:

      【解决方案3】:

      问题在于 xargs 的输出混合在一起。 GNU Parallel 就是为解决这个问题而设计的。默认情况下,它保证输出不会混合在一起。所以你可以简单地这样做:

      find folder/ | parallel ./logger.py > collab
      

      这将为每个 CPU 运行一个 logger.py。如果你想要 10:

      find folder/ | parallel -P10 ./logger.py > collab
      

      观看介绍视频以了解有关 GNU Parallel 的更多信息http://www.youtube.com/watch?v=OpaiGYxkSuQ

      【讨论】:

        猜你喜欢
        • 2015-12-04
        • 1970-01-01
        • 2012-10-26
        • 1970-01-01
        • 2018-08-07
        • 1970-01-01
        • 2014-03-10
        • 2013-03-20
        • 2016-01-29
        相关资源
        最近更新 更多