Python 使用“在循环中打印”会减慢循环速度

Python 使用“在循环中打印”会减慢循环速度,python,python-3.x,time,Python,Python 3.x,Time,在循环中使用print会减慢循环速度。打印东西(我用Hello!试过)100次需要~2秒,没有它,需要0.0秒。我使用模块time准确捕获了时间。下面是一个循环,打印在其中并显示结束时所用的时间: import time t = time.time() for _ in range(100): print("Hello! ",end = "") print("\n",time.time()-t) 输出: 这里是另一个循环,它只是将字符串添加到变量中,需要0.0秒 import t

在循环中使用
print
会减慢循环速度。打印东西(我用
Hello!
试过)100次需要~2秒,没有它,需要0.0秒。我使用模块
time
准确捕获了时间。下面是一个循环,打印在其中并显示结束时所用的时间:

import time

t = time.time()
for _ in range(100):
    print("Hello! ",end = "")

print("\n",time.time()-t)
输出:


这里是另一个循环,它只是将字符串添加到变量中,需要0.0秒

import time

t = time.time()
output = ""
for _ in range(100):
    output += "Hello! "

print(time.time()-t)
输出:


我尝试添加更多操作,但仍然需要
0.0
秒。例如:

import time

t = time.time()
output,num,count,abc = "",0,30,"H"
for _ in range(100):
    output += "Hello! "
    num += 10000
    count += 10000000
    abc += "Hello Guys!"

print(time.time()-t)



为什么
print
会减慢循环速度,我如何克服这个问题?

print()会减慢循环速度。这是因为每次调用print()时都要进行系统调用和IO操作。系统调用占用大量CPU周期,并涉及CPU上下文切换。IO操作将阻塞进程的主线程一段时间

因此,显而易见的解决方案是消除或减少print()调用的数量

如果您确实需要一种机制来了解循环的当前迭代计数,那么您可以使用多线程来实现这一点。但仍然可能涉及系统调用和线程上下文切换。但我想它仍然比print()快

诀窍是在后台线程中执行循环,同时在主线程中打印进度。这样,调用print()中的IO操作就不会阻塞运行循环的线程。为了进一步优化,您只能在用户按键时打印进度

import threading

lock = threading.Lock()
count = 0

def your_method_with_a_loop():
    global count
    with open("f.txt","w") as f:
        for q in range(1000000):
            f.write(str(q)+"\n")
            #your_logic_here
            #....
            lock.acquire()
            count = count + 1
            lock.release()

#Run the loop in a background thread
t1 = threading.Thread(target=your_method_with_a_loop)
t1.start()

while t1.isAlive():
    print("Press enter to see current loop iteration count\n")
    #use raw_input() instead if your are using python 2.x.
    input() #Remove this line if you want to print progress continuously.
    lock.acquire() 
    current_count = count
    lock.release()
    print("Current loop iteration count is ",count,"\n")
此解决方案通过两种方式改善了这种情况

  • 未在工作线程上执行IO操作。是的,使用锁涉及系统调用。但它仍然比IO块快

  • 假设python解释器使用
    futex
    实现锁,那么获取和释放锁的成本非常低,因为与工作线程相比,主线程很少持有锁


  • 你不能。木卫一很慢。您可以将所有输出存储在列表中,并在最后打印(*myoutput,sep=“\n”)它们-这将减少循环将字符串插入列表所花费的时间。这仍然需要一些时间,但稍微有些不足——除非你在存储所有输出时遇到内存问题。简明扼要;)同样对于性能测试,我会使用类似timeit:-的东西,它将执行代码10000次,并在测量时平均异常值。答案是不要将
    print()
    放入循环中。通常情况下,这是毫无意义的,只是一条势不可挡的河流。如果要监视进度,请使用类似于
    If loop\u count%1000==0:print(something)
    2:不要添加到字符串,它们是不可更改的-您一直在重建新字符串。使用列表存储字符串部分和
    ''。稍后加入(部分)
    。这就是为什么我建议使用模块。我不知道这如何缓解问题?现在你要设置锁了up@roganjosh它从两个方面改善了这种情况1。IO操作不会在运行循环的线程上执行。是的,使用锁涉及系统调用。但它仍然比IO块快。2.假设python解释器使用futex来实现锁,那么锁几乎是一个无成本的操作,与工作线程相比,主线程很少会持有锁。我将在回到PC时对此进行测试:)如果你能像这样卸载stdout,那就很有趣了。这可能是杀伤力过大。不错,我修复了几个代码错误,使其运行+1。。。ups,你也开始修复了。如果愿意,请回滚,您仍然缺少文件编写和函数定义的
    ()
    import time
    
    t = time.time()
    output,num,count,abc = "",0,30,"H"
    for _ in range(100):
        output += "Hello! "
        num += 10000
        count += 10000000
        abc += "Hello Guys!"
    
    print(time.time()-t)
    
    import threading
    
    lock = threading.Lock()
    count = 0
    
    def your_method_with_a_loop():
        global count
        with open("f.txt","w") as f:
            for q in range(1000000):
                f.write(str(q)+"\n")
                #your_logic_here
                #....
                lock.acquire()
                count = count + 1
                lock.release()
    
    #Run the loop in a background thread
    t1 = threading.Thread(target=your_method_with_a_loop)
    t1.start()
    
    while t1.isAlive():
        print("Press enter to see current loop iteration count\n")
        #use raw_input() instead if your are using python 2.x.
        input() #Remove this line if you want to print progress continuously.
        lock.acquire() 
        current_count = count
        lock.release()
        print("Current loop iteration count is ",count,"\n")