Python 显示进度

1 投票
3 回答
1113 浏览
提问于 2025-04-18 09:42

我有一段用Python写的代码,用来生成质数。我在代码中加了一小段代码(在# Start progress code# End progress code之间),用来显示操作的进度,但这样反而让操作变慢了。

#!/usr/bin/python

a = input("Enter a number: ")
f = open('data.log', 'w')

for x in range (2, a):
  p = 1
  # Start progress code
  s = (float(x)/float(a))*100
  print '\rProcessing     ' + str(s) + '%',
  # End progress code
  for i in range(2, x-1):
    c = x % i
    if c == 0:
      p = 0
      break
  if p != 0:
    f.write(str(x) + ", ")

print '\rData written to \'data.log\'. Press Enter to exit...'

raw_input()

我的问题是,怎样才能在不影响实际代码或循环速度的情况下显示操作进度呢?谢谢大家提前的帮助;-)

3 个回答

0

首先,我希望这只是个简单的问题,因为(看起来)整个操作的复杂度是O(n^2),也就是说它会随着数据量的增加变得越来越慢。

你可能想把这个放在最前面:

from __future__ import division # Make floating point division the default and enable the "//" integer division operator.

通常在处理很大的循环时,如果每次循环的开销不大,就不会在每次循环中输出进度,因为这样会花费太多时间(正如你所说的那样)。可以尝试每隔固定的次数或者固定的时间输出一次进度:

N_OUTPUTS = 100
OUTPUT_EVERY = (a-2) // 5
...
    # Start progress code
    if a % OUTPUT_EVERY == 0:
        print '\rProcessing     {}%'.format(x/a),
    # End progress code

或者如果你想按时间来控制的话:

UPDATE_DT = 0.5
import time
t = time.time()
...
    # Start progress code
    if time.time() - t > UPDATE_DT:
        print '\rProcessing     {}%'.format(x/a),
        t = time.time()
    # End progress code

这样做会稍微增加一些开销,但可以确保即使内部循环变慢,你也不会在每次循环中等待超过一次或者0.5秒,取哪个更长就用哪个。

1

你的内层循环的时间复杂度是O(n)。如果你在处理很大的数字时感觉到卡顿,那是很正常的。另外,在进行除法运算时,你把x和a转换成了浮点数;当这些数字变得更大时,这可能会让你的程序变慢。

1

为了回答你的问题,输入输出(I/O)是非常耗费资源的,所以打印你的进度会对性能产生很大的影响。如果可以的话,尽量避免打印。

如果你担心速度,有一个很好的优化方法可以大大加快你的代码运行速度。

在你的内层循环中,不要这样写:

  for i in range(2, x-1):
    c = x % i
    if c == 0:
      p = 0
      break

而是使用:

  for i in range(2, x-1**(1.0/2)):
    c = x % i
    if c == 0:
      p = 0
      break

你只需要从2开始,循环到你要测试的数字的平方根。

你可以利用这个优化来弥补因为打印进度而造成的性能损失。

撰写回答