我用python 3线程击中了死胡同。示例脚本在某种程度上是微不足道的,而它的行为与以前的python版本(使用python 2.7测试)相比有所不同
我们的想法是启动函数(to_time_it()
),它等待一个线程(thread_it()
)来清除一些标志。线程连续运行直到最后,两个函数内的sleep()确保python必须用while
语句汇集标志。
问题是,python v2(在我的情况下为.7)运行速度更快,几乎确定性更快,在我的HP(win10,Intel i5,32bit python v2.7)或更早版本上大约(10 + 5)= 15 ms linux pc。虽然相同的代码在python 3.6上运行正常,但是如果某些while循环内部存在一些无意义的print
或sleep(0)
,则会导致此10ms延迟,除外。这是代码:
# -*- coding: utf-8 -*-
import os
import time as systime
import timeit
import threading
flag = False
thread_flag = False
counter = 0
AVERAGE = 10
def thread_it():
global flag
global thread_flag
#run thread until thread_flag is not set
while not thread_flag:
while flag:
# (1)
#print("")
#systime.sleep(0)
pass
#print("!")
systime.sleep(0.05) # force to_time_it() to wait thread to set flag
flag = True # return to thread while loop
def to_time_it():
global flag
global counter
flag = False # break out of thread while loop
# - > to systime.sleep() after #(1) and than set flag
# wait thread to set flag (thread is than waiting for new cycle in it's while loop)
systime.sleep(0.03)
while not flag: # wait for flag (approx 20ms)
# (2)
#print("")
#systime.sleep(0)
pass # do nothing
print("OK: %s" %counter) # thread has cleared flag, can start new cycle
counter += 1
def main():
global thread_flag
global flag
print("Threading while loop test")
th = threading.Thread(target=thread_it)
th.start()
tajm = timeit.timeit(to_time_it, number=AVERAGE) * 1000 / AVERAGE
systime.sleep(0.7) #not neccesary, just to see what is happening when printing out data
# exit/end thread
thread_flag = True
flag = False
print("\n\tAverage time: %.2f ms" % tajm)
#os._exit(1)
if __name__ == '__main__':
main()
此代码在两个python版本上运行速度相同的点标记为# (1)
和# (2)
。事实证明,一个简单的print("")
或time.sleep(0)
进行一些内部更改,导致在python 3上运行时消除此延迟。将其中任何一个添加到点#(1)
会导致10毫秒延迟消失,并向点#(2)
添加任何内容会导致其他5毫秒消失。我不知道为什么while something: pass
的处理方式与while something: time.sleep(0)
不同。将pass
,sleep()
或print()
移至外部功能无效。
我假设有关python线程模块的一些更改必须在v3中发生,导致操作系统上下文切换/进程或线程优先级处理在较新版本上采取不同的行为。任何人都可以测试这个并解释/解释吗?
注意: I already started a similar question,但我没有得到任何回复。我开始了一个新主题(不是评论/编辑),因为我设法剥离了pyserial的测试脚本依赖项,因为我相信这是一个更普遍的python问题。请将我重定向到更好的地方,或者让我知道让专家看看这个案例的其他方法。