我正在用 Python 中的 Qt 创建一个 UI 应用程序。它在单独的
threading.Thread
中对 pandas DataFrame 执行操作,以保持 UI 响应;没有个人熊猫指令需要花费大量时间。但是,主线程中仍然存在约一秒左右的延迟。
我听说过全局解释器锁(GIL),但据我了解,它应该在几毫秒后释放。当单独的线程已经执行了一整秒时,为什么它仍然执行更多的Python指令?如何正确消除延迟?
我发现,如果我在单独的线程中撒上
time.sleep(0.00001)
,那么延迟就会消失。但这不是解决方案。
如果我在没有 pandas 的情况下使用其他一些繁重的计算(仅尝试了完全用 Python 实现的其他操作),则主线程中没有延迟。
我在以下脚本中重现了该问题。对我来说最高的 deltaTime 约为 1 秒,而评论的
sleep
约为 0.1 秒。
import threading
import time
from datetime import datetime
import pandas as pd
longest_so_far = 0
last_timestamp = datetime.now()
first_run = True
def print_delta_time(interval=0.001):
global longest_so_far
global last_timestamp
global first_run
while True:
time.sleep(interval)
current_time = datetime.now()
if first_run:
first_run = False
else:
delta_time = (current_time - last_timestamp).total_seconds()
if delta_time > longest_so_far:
print("New longest deltaTime:", delta_time)
longest_so_far = delta_time
last_timestamp = current_time
def perform_pandas_operations():
time.sleep(1)
print("Starting pandas operations")
df = pd.DataFrame({
'A': [f"{i}" for i in range(1000)],
})
for _ in range(20000):
df['A'].str.contains(r'123$').sum()
# time.sleep(0.0000001)
print("Finished pandas operations")
pandas_thread = threading.Thread(target=perform_pandas_operations)
pandas_thread.daemon = True # Ensure the thread exits when the main program exits
pandas_thread.start()
print_delta_time()
我对 numpy/scipy 案例进行了相同的观察(在单独的线程中运行
minimize
)。如果 CPU 线程不间断地运行,它可以使 Tkinter 线程饥饿任意长时间。至少在 Windows 下(尚未在 Linux 中尝试过)。
解决方案确实是进行接近零时间的睡眠。这似乎向调度程序发出信号,表明该线程可以挂起,而其他线程有机会运行。当然,这要求您至少有一些可以放置该调用的“断点”。
实际上,您可以利用它来获得有益的效果:
time.sleep
替换为threading.Event.wait
,并将该事件用作“取消”标志,以允许中断计算。