如何在 python 脚本退出时终止线程(如果需要)?

How do I kill my thread on python script exit(If I need to)?

我正在开发一个每秒从 API 中获取数据的程序。所以我有一个名为 tick 的函数,它基本上是来自 API 的 returns 数据。为了能够在等待响应的时候每秒不卡顿地使用GUI,我把它放在一个线程上,像这样:

def every(delay, task):
  next_time = time.time() + delay
  while True:
    time.sleep(max(0, next_time - time.time()))
    try:
      task()
    except Exception:
      traceback.print_exc()
      # in production code you might want to have this instead of course:
      # logger.exception("Problem while executing repetitive task.")
    # skip tasks if we are behind schedule:
    next_time += (time.time() - next_time) // delay * delay + delay

    ...
    ...

threading.Thread(target=lambda: every(1, tick)).start()

window.mainloop()

当我关闭 GUI window 时,python 控制台变得像这样疯狂:

Traceback (most recent call last): File "D:/PycharmProjects/test/test.py", line 22, in every task() File "D:/PycharmProjects/test/test.py", line 66, in tick insert_text(unn1, unn_text) File "D:/PycharmProjects/test/test.py", line 47, in insert_text entry.delete(0, END) File "D:\Python37\lib\tkinter__init__.py", line 2676, in delete self.tk.call(self._w, 'delete', first, last) RuntimeError: main thread is not in main loop

我很清楚线程没有终止。但是我是 python 和线程的新手,所以我不知道这个线程是否需要从代码中关闭,或者当我实际上是 运行 编译程序时它会自动关闭它我关闭程序 window。那么,我需要从内部关闭它吗?如果是这样,我该如何正确操作?

您可以使用全局变量(即 running)来控制 while 循环。

之后你也可以使用thread.join()等待线程结束。

def every(delay, task):
  global running 

  next_time = time.time() + delay

  while running:
      ...
      ...

#---------------------------------------------

running = True
thread = threading.Thread(target=lambda: every(1, tick))
thread.start()

window.mainloop()

running = False # it will end `while` loop
thread.join()   # it will wait for end of thread

如果 task 时间不长,那么您可以使用 after() 而不是线程和 while 循环。类似于

def every(delay, task):
    start = time.time()

    try:
       task()
    except Exception:
       traceback.print_exc()

    end = time.time()
    diff = end - start
    after_time = max(0, delay - diff)

    if running:
        window.after(after_time, every, (1000, task)) # 1000ms=1s

#---------------------------------------------

running = True

window.every(1000, tick) # 1000ms=1s
window.mainloop()

running = False # it will end `while` loop