Python hashlib返回结果不一致,请求排查代码问题
问题排查:哈希值每次计算不一致的原因及修复方案
我编写的代码每次运行时,
hasher.hexdigest()返回的结果都不一致,但files列表中的文件从未发生修改。需求是仅当当前配置文件中的校验和与这三个文件通过hashlib计算出的哈希值不匹配时,才生成新的配置文件。请帮忙排查代码问题:
def should_generate_new_settings(qt_settings_generated_path: Path) -> tuple[bool, str]: """ compare checksum of user_settings.json and the current ini file to what is stored in the currently generated settings file """ generate = False hasher = hashlib.new('md5') if not qt_settings_generated_path.exists(): generate = True try: # if the file is corrupt, it may have a filesize of 0. generated_file = qt_settings_generated_path.stat() if generated_file.st_size < 1: generate = True files = [paths.user_settings_path, paths.settings_generated_path, Path(__file__)] for path in files: file_contents = path.read_bytes() hasher.update(file_contents) with qt_settings_generated_path.open('r') as file: lines = file.read().splitlines() checksum_prefix = '# checksum: ' for line in lines: if line.startswith(checksum_prefix): file_checksum = line.lstrip(checksum_prefix) if file_checksum != hasher.hexdigest(): generate = True break except FileNotFoundError: generate = True return (generate, hasher.hexdigest())
问题原因及修复
核心问题
你将生成后的配置文件本身(paths.settings_generated_path)加入了哈希计算的文件列表,而这个文件每次生成时会写入新的校验和,内容必然变化,导致每次计算的哈希值不一致。此外,代码逻辑冗余,哈希对象初始化和更新时机不合理,可能导致异常场景下哈希计算不完整。
修复方案
- 移除生成文件的校验:仅将原始配置文件(
paths.user_settings_path)和脚本文件(Path(__file__))纳入哈希计算,这两个文件才是决定是否需要重新生成配置的依据。 - 优化逻辑顺序:先判断生成文件的存在性和完整性,符合条件时直接返回生成结果,避免后续不必要的操作。
- 独立初始化哈希对象:每次计算哈希都重新创建
hasher,确保计算过程独立,无累计更新问题。
修正后的代码
def should_generate_new_settings(qt_settings_generated_path: Path) -> tuple[bool, str]: """比较user_settings.json、当前脚本文件的校验和与已生成配置文件中存储的校验和,判断是否需要生成新配置""" # 先判断是否需要直接生成新配置 if not qt_settings_generated_path.exists() or qt_settings_generated_path.stat().st_size < 1: hasher = hashlib.new('md5') # 仅校验原始配置和脚本文件 files = [paths.user_settings_path, Path(__file__)] for path in files: file_contents = path.read_bytes() hasher.update(file_contents) return (True, hasher.hexdigest()) try: # 计算当前基准文件的哈希值 hasher = hashlib.new('md5') files = [paths.user_settings_path, Path(__file__)] for path in files: file_contents = path.read_bytes() hasher.update(file_contents) current_checksum = hasher.hexdigest() # 读取并对比已生成文件中的校验和 with qt_settings_generated_path.open('r') as file: checksum_prefix = '# checksum: ' for line in file: line = line.strip() if line.startswith(checksum_prefix): stored_checksum = line.lstrip(checksum_prefix).strip() if stored_checksum != current_checksum: return (True, current_checksum) break # 校验和匹配或未找到校验行,无需生成 return (False, current_checksum) except FileNotFoundError: # 兜底异常处理,重新计算哈希并返回需要生成 hasher = hashlib.new('md5') files = [paths.user_settings_path, Path(__file__)] for path in files: file_contents = path.read_bytes() hasher.update(file_contents) return (True, hasher.hexdigest())
内容的提问来源于stack exchange,提问作者Ryan Glenn
相关产品推荐
相关产品推荐

