You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python多线程间共享可更新的saved_session以复用代理会话?

问题分析与解决方案

你的问题主要源于两个核心问题:普通字典的线程不安全特性,以及线程创建方式错误。以下是具体的修复方案:

1. 核心问题说明

  • 普通Python字典不是线程安全的,多线程同时读写时会出现数据竞争,导致写入的会话数据无法被其他线程读取到。
  • 你在创建线程时,错误地将target设置为函数调用(from_page(url,)),这会直接在主线程执行函数,而非启动子线程运行,导致多线程逻辑完全失效。

2. 完整修复代码

导入线程锁并初始化全局资源

from threading import Thread, Lock

import test_by_me

# 保存会话的字典
saved_session: dict = {}
# 线程锁,用于同步对saved_session的读写操作
session_lock = Lock()

修改注入函数,加锁写入会话数据

def injection(session, response):
    if test_by_me.challenge(session, response):
        solve = test_by_me.solve(session, response)

        # 加锁保证写入操作的原子性,避免多线程冲突
        with session_lock:
            # 复制headers和cookies,避免后续修改session影响已保存的会话
            saved_headers = session.headers.copy()
            saved_cookies = session.cookies.copy()
            saved_session[session.proxies["https"]] = {
                "headers": saved_headers,
                "cookies": saved_cookies
            }

        return solve
    else:
        return response


def create_session():
    return test_by_me.create_scraper(
        Hook=injection,
    )

修改线程执行函数,加锁读取会话数据

def from_page(url):
    while True:
        with create_session() as session:
            proxy = proxies.random_proxies()
            session.proxies = {'https': proxy}

            # 加锁读取最新的会话数据
            with session_lock:
                proxy_session = saved_session.get(proxy)
                if proxy_session:
                    # 使用update方法合并headers,避免覆盖session默认配置
                    session.headers.update(proxy_session['headers'])
                    # 恢复保存的cookies
                    session.cookies.update(proxy_session['cookies'])

            resp = session.get(url, timeout=6)
            # 后续业务逻辑处理
            ...

修正主线程的线程创建方式

def main() -> None:
    db_urls = [...]

    # 正确创建线程:target为函数对象,args传递参数元组
    for url in db_urls:
        Thread(target=from_page, args=(url,)).start()


if __name__ == '__main__':
    main()

3. 关键修复点解释

  • 线程锁(Lock):通过with session_lock上下文管理器,确保同一时间只有一个线程能读写saved_session,彻底避免数据竞争问题。
  • 会话数据复制:对headers和cookies进行复制操作,防止后续修改当前session时,意外污染已保存的会话数据。
  • 线程创建修正:将target设置为函数本身,通过args传递参数,确保函数在子线程中执行,而非主线程直接调用。

4. 额外优化建议

  • 可以给保存的会话添加过期时间,定期清理失效的代理会话,避免内存占用过高。
  • 如果代理数量极大或读写操作频繁,可以考虑使用concurrent.futures.ThreadPoolExecutor简化线程管理,同时保持锁机制不变。

内容的提问来源于stack exchange,提问作者PythonNewbie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 15:27:21