PyCharm运行doctest时自定义异常作用域不一致的原因及解决方法
问题解答
1. PyCharm运行doctest与其他方式的差异
PyCharm自动生成的单模块doctest运行配置,核心逻辑是将模块所在的目录直接加入sys.path头部,以顶层模块的形式导入目标模块:
- 你的my_module.py放在my_package目录下,PyCharm运行doctest时会把my_package目录加入Python搜索路径,直接
import my_module,此时模块的__name__属性为my_module,自定义异常类Mayday的__module__属性同样为my_module,异常抛出时打印的前缀自然就是my_module.Mayday。 - 而pytest等常规运行方式,通常会将项目根目录加入sys.path,以包结构导入模块
import my_package.my_module,此时模块__name__为my_package.my_module,异常打印就会带上完整包前缀。 - PyCharm自带控制台默认将项目根目录加入sys.path,导入逻辑和pytest一致,所以抛出的异常会带完整包名,和doctest运行时的模块导入逻辑不同,才会出现表现矛盾的情况。
2. 跨场景兼容的解决方案
下面是两种最通用的兼容方案:
方案1:使用doctest省略号匹配(推荐)
doctest默认支持...作为通配符匹配任意长度的任意内容,直接修改预期异常行即可:
def raisins(): """ >>> raisins() Traceback (most recent call last): ... ...Mayday: Yikes! """ raise Mayday('Yikes!')
这种写法完全屏蔽了模块前缀的差异,不管是PyCharm单模块运行还是pytest全量运行都能匹配通过,不需要额外配置。
方案2:主动捕获异常打印,规避模块前缀
如果不想依赖通配符,你可以修改doctest用例的写法,主动捕获异常后打印类名和异常信息,完全避开模块前缀的匹配:
def raisins(): """ >>> try: ... raisins() ... except Mayday as e: ... print(type(e).__name__, str(e)) Mayday Yikes! """ raise Mayday('Yikes!')
这种写法的测试匹配逻辑更严谨,不会出现通配符可能带来的误匹配问题。
内容的提问来源于stack exchange,提问作者CodeNStuff
相关产品推荐
相关产品推荐

