多线程场景下Python Requests库请求头(Access Token)混叠问题
嘿,我一眼就认出这个坑了!你遇到的根本不是requests.Session的线程安全问题,而是Python里可变默认参数的经典陷阱!
问题出在哪?
看你ApiConnector里的__request方法定义:
def __request(self, method, path, payload={}, auth=False, headers={}):
在Python中,函数的可变默认参数(比如这里的headers={})是在函数定义的时候就创建好了,而不是每次调用函数时新建。这意味着所有线程调用这个方法时,共用的是同一个字典对象!
当多个线程同时往这个共享的headers里写Accept或者Authorization头时,就会互相覆盖——比如User-3刚把自己的token塞进去,User-1的线程紧接着把自己的token写进去,最后发送请求时用的就是最后写入的那个token,这就导致了你看到的「IN的token正确,但OUT的token变成别人的」诡异情况。
怎么修复?
很简单,把可变默认参数改成None,然后在函数内部初始化新的空对象,确保每个线程都用自己独立的字典:
修改后的__request方法:
def __request(self, method, path, payload=None, auth=False, headers=None): # 给默认参数创建新的空对象,避免线程共享 payload = payload if payload is not None else {} headers = headers if headers is not None else {} url = f"{self.base_url}{path}" headers["Accept"] = "application/json" if auth: if not self.__is_authenticated(): self.__authenticate() headers["Authorization"] = "Bearer " + self.__auth_token print(f"[{self.user}] IN => {path} - {self.__auth_token}") # 后续的请求逻辑保持不变...
这样每次调用__request时,都会生成全新的headers和payload字典,各个线程之间完全隔离,再也不会出现头信息混叠的问题了。
补充说明
你提到requests的Session是线程安全的,这点没错——每个ApiConnector实例都有自己的self.session,这部分是没问题的。问题完全出在你自己用了共享的可变默认参数,和Session本身无关。另外把payload={}也改成None初始化,能避免未来可能出现的其他并发隐患,算是个好习惯。
内容的提问来源于stack exchange,提问作者Arkaik
相关产品推荐
相关产品推荐

