Python调用API自动注册账号程序使用多线程后终端输出混乱如何解决?
问题原因及修复方案
核心问题梳理
- 输出混乱:多线程并发调用
print时,print不是原子操作,多个线程的输出内容会被操作系统调度打断,出现行交错、内容拼接混乱的问题。 - 共享变量线程不安全:
self.checkedCount、self.availableCount、self.errorCount等实例变量为所有线程共享,并发修改时会出现计数丢失错误,最终统计结果不准。 - 队列逻辑错误:
checker方法内重复加载词表到队列,且用户名get后立刻put回队列,会导致同一个用户名被无限重复检测,完全浪费性能。 - 共享请求头无保护:如果
self.accounts()方法会修改self.headers刷新权限,多线程同时读写请求头会导致请求校验失败,异常率升高。
修复方案
1. 新增线程锁
在类的__init__初始化方法中添加线程锁,保护所有共享资源的读写:
import threading class YourClassName: def __init__(self): # 原有初始化逻辑不变,新增下面这行 self.lock = threading.Lock()
2. 修正队列逻辑
删除checker方法首行加载词表的代码,用户名处理完成后不再放回队列:
def checker(self): # 删除这行:[self.usernames.put(line.strip()) for line in open("external/wordlist.txt")] while not self.usernames.empty(): # 删除后面的put操作,只保留get name = self.usernames.get() # 后面原有逻辑不变
3. 加锁保护输出和共享变量修改
所有print、计数变量修改、self.headers修改的位置都加锁:
示例修改后的checker核心片段:
def checker(self): while not self.usernames.empty(): name = self.usernames.get() url = f"https://public-ubiservices.ubi.com/v3/profiles?nameOnPlatform={name}&platformType=uplay" try: r = requests.get(url, headers=self.headers) # 加锁操作共享变量和输出 with self.lock: if self.checkedCount % 100 == 0: self.checkedCount += 1 print(f"{Fore.LIGHTBLACK_EX}[+]{Fore.RESET} Message: Using new login") self.accounts() ctypes.windll.kernel32.SetConsoleTitleW(f"Gx | Checked: {self.checkedCount}, Available: {self.availableCount}, Errors: {self.errorCount}") if r.status_code == 200: self.checkedCount += 1 if len(r.json()['profiles']) != 0: print(f"{Fore.LIGHTBLACK_EX}[+]{Fore.RESET} Taken: {name}") else: print(f"{Fore.LIGHTBLACK_EX}[+]{Fore.RESET} Available: {name}") self.availableCount += 1 self.create(name) else: self.errorCount += 1 print(f"{Fore.LIGHTBLACK_EX}[+]{Fore.RESET} Error: Check errors.txt") with open('external/errors.txt', "a") as errorFile: errorFile.write(f'{self.currentTime} | Error code: {r.status_code}, Error message: {r.text}\n') self.checkedCount += 1 self.accounts() except Exception: with self.lock: self.errorCount += 1 pass
4. 可选优化
如果不想自己管理打印锁,可以直接用Python标准库的logging模块输出日志,logging默认是线程安全的,无需额外加锁即可保证输出不乱。
内容的提问来源于stack exchange,提问作者user16246484
相关产品推荐
相关产品推荐

