import itertools
import time
from threading import Thread, Event
def spin(msg: str, done: Event) -> None:
for char in itertools.cycle(r'\|/-'): # 1
status = f'\r{char}{msg}' # 2
print(status, end='', flush=True)
if done.wait(.1): # 3
break # 4
blanks = ' ' * len(status)
print(f'\r{blanks}\r', end='') #5
def slow() -> int:
time.sleep(3) # 7
return 42
'''
1. 这是一个无限循环,因为itertools.cycle 一次产出一个字符,一直反复迭代字符串
2. 用文本实现动画的技巧: 使用ASCCI 回车符('\r') 把光标移动到行头
3. 如果其他线程设置了set(),则Event.wait(timeout=None) 方法返回True
如果其他线程未设置set(), 则经过timeout 时间后返回False,这里把暂停时间设置为0.1秒,作用是把动画的
帧率设为10fps。如果想指针旋转的快些,可以把值设置的小一些
4. 退出无限循环
5. 显示空格,并把光标移到开头,清空状态行
6.slow() 由主线程调用。假设有一个API通过网络发送,速度很慢。调用sleep 阻塞主线程,但是GIL已被释放,因此指针还能继续转动
'''
def supervisor() -> int:
done = Event()
spinner = Thread(target=spin, args=('thinking!', done))
print(f'spinner object:{spinner}')
spinner.start()
result = slow()
done.set()
spinner.join()
return result
def main() -> None:
result = supervisor()
print(f'AnswerL: {result}')
if __name__ == '__main__':
main()
运行中:
运行结束:
通过这个实例,要了解最重要的一点:
调用 time.sleep()阻塞所在的线程,但是释放GIL,其他Pyhton线程可以继续运行
在Python中,协调线程的信号机制,使用threading.Event 类最简单。Event 实例有一个内部布尔标志,开始时为False,
调用Event.set() 可把这个标志设为True。这个标志为False时,在一个线程中调用Event.wait(),该线程将被阻塞,直到另一个线程
调用Event.set(),致使Event.wait()返回True。使用Event.wait(s) 设置一个暂停时间(单位秒),经过这段时间后,Event.wait(s)
调用返回False,如果一个线程调用Event.set(),则立即返回True
标签:set,Python,模型,spinner,并发,调用,线程,Event,wait
From: https://www.cnblogs.com/czzz/p/17383269.html