我有一个多线程程序,最近遇到了一个有趣的现象。
如果我在线程的工作程序中调用print
方法,程序将变得非常被动。没有什么大把戏,只需调用print
方法即可解决所有问题。
我最近读了一篇有关Python的Global Interpreter Lock aka GIL的文章,它说一旦执行I / O绑定的东西,GIL就被释放。您是否认为print
调用也是I / O绑定的?
我真的很想让我的程序具有响应性,但是在运行时将数据转储到stdout上显然很尴尬。因此,我尝试将输出重定向到/dev/null
,但未能解决问题:
with contextlib.redirect_stdout(None):
print('')
如果您有一个主意,希望能通过以下调用重现相同的效果,但又不丢失任何内容,请多加感谢:
print('')
据我所见,解释器为print('')
工作时释放了GIL。也许我需要短暂休息一下,让我摆脱GIL。
这仅供参考,但我尝试调用以下方法:
print('', end='', flush=True)
当然,它没有转储任何东西,但我的程序变得有点锯齿,看起来该线程已经占用了执行时间,因此其他线程很少运行。
更新
如果我呼叫QThread的usleep(1)
希望让它睡1个小时,那么它的等待时间将比我指定的要长得多。例如。线程工作程序每1毫秒运行一次,这非常慢,因为我希望以微秒的顺序运行它。调用print('')
使线程以几微秒的顺序运行。在这种意义上,我称之为反应性。
更新
我觉得有些事情在浪费线程的执行时间,但不是usleep
或time.sleep()
。但是,我遇到了一个事实,print
可以将阻止程序踢开。所以我想知道实际上是什么在踢阻拦物。
答案 0 :(得分:1)
因此,这里发生了两件事。首先,对于GIL本身,大多数I / O函数都会在调用平台代码之前将其释放,因此,print
调用肯定会释放它。这自然会让运行时调度另一个线程。
第二,对于usleep
,此功能可以保证至少休眠 与您要求的一样多,而几乎不休眠 OS调度程序刻度的持续时间。在Linux上,它通常以1,000 Hz,250 Hz或100 Hz的频率运行,但可能会有很大差异。
现在,如果您想要更细粒度的内容,可以进行nanosleep
调用,该调用将“忙等待”不到2 ms的延迟,而不是调用内核。