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

处理ImportError异常遇问题:RIPEMD160多fallback方案失效

问题分析与解决

我写了一段带两级降级逻辑的RIPEMD160哈希实现代码:优先依赖编译有RIPEMD160支持的OpenSSL(OpenSSL 3.0默认不再支持),其次依赖未声明依赖的第三方包,最后用纯Python实现。但测试时发现,当OpenSSL不支持且第三方包未安装时,抛出的ModuleNotFoundError未被ImportError捕获,程序直接报错,这是为什么?

代码示例

import hashlib

assert issubclass(ModuleNotFoundError, ImportError)


def sha256(public_key: bytes) -> bytes:
    return bytes(hashlib.sha256(public_key).digest())


def hash_160(public_key: bytes) -> bytes:
    sha256_hash = sha256(public_key)
    try:
        md = hashlib.new("ripemd160")
        md.update(sha256_hash)
        return md.digest()
    except ValueError:
        from Crypto.Hash import RIPEMD160
        md = RIPEMD160.new()
        md.update(sha256_hash)
        return md.digest()
    except ImportError:
        # from . import ripemd
        # md = ripemd.new(sha256_hash)
        # return md.digest()
        return b""


print(hash_160(b"very test"))

报错信息

Traceback (most recent call last):
  File "/usr/lib/python3.10/hashlib.py", line 160, in __hash_new
    return _hashlib.new(name, data, **kwargs)
ValueError: [digital envelope routines] unsupported

During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/home/pierre/dev/test_package/./package1/tests/module1.py", line 14, in hash_160
    md = hashlib.new("ripemd160")
  File "/usr/lib/python3.10/hashlib.py", line 166, in __hash_new
    return __get_builtin_constructor(name)(data)
  File "/usr/lib/python3.10/hashlib.py", line 123, in __get_builtin_constructor
    raise ValueError('unsupported hash type ' + name)
ValueError: unsupported hash type ripemd160

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/pierre/dev/test_package/./package1/tests/module1.py", line 31, in <module>
    print(hash_160(b"very test"))
  File "/home/pierre/dev/test_package/./package1/tests/module1.py", line 18, in hash_160
    from Crypto.Hash import RIPEMD160
ModuleNotFoundError: No module named 'Crypto'

问题根源

尽管ModuleNotFoundError确实是ImportError的子类,但当前代码的异常捕获逻辑存在层级问题:

  • 外层try块仅负责捕获hashlib.new("ripemd160")抛出的ValueError
  • 当进入except ValueError块执行导入语句时,抛出的ModuleNotFoundError属于该内部代码的异常,不在外层try的捕获范围内,因此会直接向外抛出,不会触发后面同级的except ImportError块。

修复方案

需要将第三方包的导入逻辑放到嵌套的try-except块中,才能捕获导入失败的异常:

import hashlib

assert issubclass(ModuleNotFoundError, ImportError)


def sha256(public_key: bytes) -> bytes:
    return bytes(hashlib.sha256(public_key).digest())


def hash_160(public_key: bytes) -> bytes:
    sha256_hash = sha256(public_key)
    try:
        md = hashlib.new("ripemd160")
        md.update(sha256_hash)
        return md.digest()
    except ValueError:
        # 嵌套try块捕获第三方包导入失败的异常
        try:
            from Crypto.Hash import RIPEMD160
            md = RIPEMD160.new()
            md.update(sha256_hash)
            return md.digest()
        except ImportError:
            # 执行纯Python实现
            # from . import ripemd
            # md = ripemd.new(sha256_hash)
            # return md.digest()
            return b""


print(hash_160(b"very test"))

另一种方案是提前在模块加载阶段尝试导入第三方包,避免函数内嵌套:

import hashlib

# 提前尝试导入第三方包,标记是否可用
try:
    from Crypto.Hash import RIPEMD160
    HAS_CRYPTO = True
except ImportError:
    HAS_CRYPTO = False

assert issubclass(ModuleNotFoundError, ImportError)


def sha256(public_key: bytes) -> bytes:
    return bytes(hashlib.sha256(public_key).digest())


def hash_160(public_key: bytes) -> bytes:
    sha256_hash = sha256(public_key)
    try:
        md = hashlib.new("ripemd160")
        md.update(sha256_hash)
        return md.digest()
    except ValueError:
        if HAS_CRYPTO:
            md = RIPEMD160.new()
            md.update(sha256_hash)
            return md.digest()
        # 执行纯Python实现
        # from . import ripemd
        # md = ripemd.new(sha256_hash)
        # return md.digest()
        return b""


print(hash_160(b"very test"))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 20:35:07