Python中能否缓存joserfc.jwk.RSAKey.import_key的(string,key)?Pickle存key失败
解决pytest中joserfc RSAKey缓存的pickle序列化问题
问题原因
你遇到的pickle错误,是因为joserfc.jwk.RSAKey内部包含了cryptography库的底层Rust绑定对象(cryptography.hazmat.bindings._rust.openssl.rsa.RSAPrivateKey),这类和系统底层资源绑定的对象不支持pickle序列化,直接缓存key对象会失败。
下面是几种可行的解决方案:
方案1:内存级缓存(单测试会话复用)
用functools.lru_cache给import_key做一层包装,在单次pytest运行会话内,重复的密钥字符串会直接返回缓存好的key对象,不用重复解析,速度最快:
from functools import lru_cache import joserfc.jwk @lru_cache(maxsize=None) def get_cached_rsa_key(key_string: str) -> joserfc.jwk.RSAKey: return joserfc.jwk.RSAKey.import_key(key_string)
之后测试代码里统一调用get_cached_rsa_key(your_key_string)即可,重复的密钥字符串只会被解析一次。
方案2:持久化缓存(跨测试会话复用)
如果需要跨多次pytest运行复用缓存,不要直接存key对象,而是将key导出为可序列化的PEM字符串,缓存字符串后再按需重新导入:
用自定义文件缓存
import pickle import joserfc.jwk from pathlib import Path CACHE_FILE = Path("rsa_key_cache.pkl") # 加载已有缓存 try: with open(CACHE_FILE, "rb") as f: _rsa_cache = pickle.load(f) except (FileNotFoundError, EOFError): _rsa_cache = {} def get_cached_rsa_key(key_string: str) -> joserfc.jwk.RSAKey: if key_string in _rsa_cache: return joserfc.jwk.RSAKey.import_key(_rsa_cache[key_string]) key = joserfc.jwk.RSAKey.import_key(key_string) # 将key导出为PEM字符串存入缓存 _rsa_cache[key_string] = key.export_to_pem() # 持久化缓存到文件 with open(CACHE_FILE, "wb") as f: pickle.dump(_rsa_cache, f) return key
用pytest自带缓存机制
利用pytest内置的cache fixture实现跨会话缓存,无需自己管理文件:
import joserfc.jwk def get_cached_rsa_key(key_string: str, request) -> joserfc.jwk.RSAKey: # 用哈希值作为缓存键,避免长字符串占用空间 cache_key = f"rsa_keys/{hash(key_string)}" cached_pem = request.config.cache.get(cache_key, None) if cached_pem: return joserfc.jwk.RSAKey.import_key(cached_pem) key = joserfc.jwk.RSAKey.import_key(key_string) request.config.cache.set(cache_key, key.export_to_pem()) return key
使用时在测试函数中传入request fixture即可:
def test_something(request): key_str = "your_rsa_key_string" key = get_cached_rsa_key(key_str, request) # 执行测试逻辑
内容的提问来源于stack exchange,提问作者Jon Jagger
相关产品推荐
相关产品推荐

