Python不会解压缩打印语句

时间:2012-11-28 23:45:59

标签: python output-buffering

我有以下程序:

def main():
    print "Running"
    primes = sieve(100000)
    print "Sieve is done"

def sieve(n):
    print "starting sieve"
    primes = []
    times = 0

    numbers = range(2, n):
    print "sieve array filled"

    while len(numbers) > 0:
        current = numbers[0]
        primes.append(current)
        numbers.remove(current)

        times = times + 1
        if (times % 10 == 0):
            print str(times) + "th prime is " + str(current)

        # Remove every multiple
        for i in numbers:
            if (i % current == 0):
                numbers.remove(i)

当找到大量的素数(比如一万个)时,我希望通过查看输出能够看到程序的距离。所以我决定打印每十个素数。但是,当打印出来时,它会一直等到程序的最后才打印出来。我在打印声明之后立即添加了sys.stdout.flush(),但它没有任何区别。然后我尝试使用python -u <file name>运行脚本,但仍然没有任何区别。

这是我得到的输出:

Running
starting sieve
sieve array filled

大约一分钟后,其余的输出会立即显示出来。

为什么我不能关闭缓冲区?我试图尽可能少地修改代码。

3 个答案:

答案 0 :(得分:3)

测试了一些东西,我不确定你的问题实际上是输出缓冲,它只是算法的行为。尝试在current循环顶部附近打印while,您会发现早期数字需要很长时间才能完成,然后随着numbers变得越来越短, current的每个新值都可以更快地处理,并且您会开始看到素数弹出。

尝试:

while len(numbers) > 0:
    current = numbers[0]
    print current
    primes.append(current)
    numbers.remove(current)

答案 1 :(得分:2)

这个速度太慢的原因是从数字中删除元素的循环:

    # Remove every multiple
    for i in numbers:
        if (i % current == 0):
            numbers.remove(i)

每次删除一个数字时,Python都必须移动所有元素,然后将该数字移回一个地方。每次删除都是O(n)*,你做O(n)删除,所以这一步的每次迭代需要O(n ^ 2)次。

如果用列表推导替换它,那么Python将从旧列表中构建一个新列表 - 不涉及移动 - 这是一个O(n)操作。这是我做这一步的方式:

    # Remove every multiple
    numbers = [i for i in numbers if (i % current) != 0]

通过此更改,您的代码可以更快地以方式运行。它在5秒内完成,并且没有输出缓冲问题。

* Python列表操作here有一个很好的时间复杂表。

答案 2 :(得分:0)

尝试使用sys.stdout.write代替print。这应该更适合sys.stdout.flush