8

我正在使用这样的东西:

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}

我该如何预防/纠正这种情况?

4

3 回答 3

2

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

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

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

于 2011-02-16T22:40:20.603 回答
1

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

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

于 2011-02-16T22:38:46.357 回答
1

问题是 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

于 2011-02-17T13:53:16.393 回答