Python中如何非阻塞使用threading?解决线程启动阻塞问题
问题根源
- 线程初始化时,
threading.Thread(target=handler.run())这行代码犯了核心错误:直接执行了handler.run()方法,而非将方法本身作为线程的目标函数。由于run()内部是无限循环,主线程会直接卡在这个调用里,根本走不到后续的线程启动逻辑,导致只打印第一个debug1就彻底阻塞。
修复步骤
1. 修正线程目标函数的传递方式
把target=handler.run()改成target=handler.run,这样才是把方法对象传给线程,让线程去执行这个方法,而非主线程直接执行。
2. 补充缺失的依赖与定义
- 代码里用了
json.dump却没导入json模块,需添加import json。 - 代码里调用
threads.append(t)但未初始化threads列表,需在开头添加threads = []。
3. 给线程添加优雅停止机制(推荐)
原代码中线程是无限循环,即使主线程退出,守护线程虽会随主线程结束,但更稳妥的方式是添加停止标志,让线程正常退出:
- 在
Handler类里加self.running = True作为停止标志; - 把
run方法的循环条件改成while self.running; - 在信号处理函数里遍历线程,设置每个
handler的running为False,等线程结束后再写入文件。
完整修复后的代码
import sys import time import threading import signal import json from functools import partial messages = {} lock = threading.Lock() threads = [] # 初始化线程列表 class Handler: def __init__(self, port): self.port = port self.running = True # 添加停止标志 def run(self): while self.running: # 使用停止标志代替无限循环 time.sleep(1) with lock: messages[self.port].append(time.time()) def signal_handler(filename, sig, frame): # 通知所有线程停止 for t in threads: t._target.__self__.running = False # 等待所有线程结束 for t in threads: t.join() # 写入文件 with lock: with open(filename, "w") as fileout: json.dump(messages, fileout) sys.exit(0) output = "test.out" signal.signal(signal.SIGINT, partial(signal_handler, output)) for port in [1,2]: messages[port] = [] handler = Handler(port) print("debug1") t = threading.Thread(target=handler.run) # 修正:传递方法对象而非调用结果 print("debug2") t.daemon = True t.start() threads.append(t) # 保持主线程运行,等待CTRL-C try: while True: time.sleep(1) # 替换空循环,减少CPU占用 except KeyboardInterrupt: signal_handler(output, signal.SIGINT, None)
额外优化说明
- 把原代码的空循环
while True: pass改成while True: time.sleep(1),避免主线程空转占用过多CPU资源。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

