4

我有两个 Python 脚本在 Ubuntu Linux 机器上运行。第一个将其所有输出发送到标准输出,第二个从标准输入读取。它们通过一个简单的管道连接,例如:

./step1.py <some_args> | ./step2.py <some_other_args>

step2 所做的是它在无限循环中读取输入行并处理它们:

while True:
    try:
        l = sys.stdin.readline()
        # processing here

Step1 不时崩溃。当这种情况发生时(不确定是否总是,但至少在几次情况下)不是崩溃/停止,而是 step2 变得疯狂并开始占用 100% 的 CPU,直到我手动杀死它。

为什么会发生这种情况,如何使 step2 更加健壮,以便在管道破裂时停止?

谢谢!

4

2 回答 2

3

当 step1 终止时,您将有一个 while 循环,其中包含一个 try 语句,该语句将引发异常。因此,您将使用 100% 的 CPU 不断尝试并失败,因为 readline 在抛出异常时不会阻塞。

要么为读取添加时间延迟,要么time.sleep更好地注意 readline 抛出的错误,并捕获当 step1 停止并退出程序而不是尝试从死管道中读取时抛出的特定错误。

当管道为空时,您可能需要一个睡眠操作员,而当管道死亡时,您可能需要一个退出,但是在每种情况下都会抛出哪个异常以及什么消息,我将作为练习留给您确定。在这种情况下,睡眠运算符不是必需的,但它可以避免在无用工作上导致 CPU 使用率过高的其他情况。

于 2012-09-10T17:19:06.860 回答
3

其他人已经解释了为什么在某些情况下你会陷入无限循环。

在第二个(阅读)脚本中,您可以使用成语:

for line in sys.stdin:
    process(line)

这样你就不会陷入无限循环。此外,您实际上并没有显示您尝试在第二个脚本中捕获哪个异常,但我猜您会不时遇到“破管”错误,您可以并且应该按照此处所述捕获:如何处理python中的破损管道(SIGPIPE)?

整个方案可能如下所示:

try:
    for line in sys.stdin:
        process(line)
except IOError, e:
    if e.errno == errno.EPIPE:
        # EPIPE error
    else:
        # Other error
于 2012-09-10T17:22:23.337 回答