V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
LeeReamond
V2EX  ›  Python

想要开发一个供 Python 使用的静态类型检查项目

  •  
  •   LeeReamond · 2021-01-27 19:31:50 +08:00 · 1756 次点击
    这是一个创建于 1430 天前的主题,其中的信息可能已经有所发展或是发生改变。

    不知道有没有类似项目,如果有的话请告诉我,

    昨天发了个贴问了一下类型提示的循环导入问题,产生了一些发散式联想,能不能把现有的体系再升级一下做成一个自动检查项目,应该会挺有用的。

    目前我司对于类型检查使用的是比较原始的方法,即手动增加装饰器,装饰器可以接管函数或方法的控制权,检查输入和输出是否符合标准。

    而如果升级成框架的话,大概想了一下应该具有三种功能。

    其一是类似直接引入式的用法,即可以嵌入一个通常程序中,对其中某个节点做检查,也是我们现在正在用的方法,这个技术上难度不大。

    from 框架 import 类型检查
    
    @类型检查
    def func(a:int , b:str) -> None:
        ...
    
    func()
    

    其二是全局接管式,即通过修改 entrypoint 以命令行启动程序,替换 python3,对全局中的所有有类型标注的内容做检查。

    root@vhost~# python3 main.py
    替换成
    root@vhost~# typecheck main.py
    

    其三是接入 pytest,这个应该算是另外一个项目,比如做成 pytest 插件,暂不谈。

    =============

    这个项目的目的是在开发阶段,以及自动测试当中进行严格的类型约束,使程序在实际生产环境中关闭类型约束后仍然具有较高鲁棒性。它的好处是可以在最小侵入性的前提下(即保留 python 的设计哲学,pythoner 显然无意将 python 改变为一门静态类型语言,但可以通过掐头去尾的方式大幅提可靠性和降低维护难度)这是我个人的想法,我生产经验也不是特别丰富,如有错误各位指正。

    大概思考了一下实现的困难,

    其一是使用符合 PEP484 的类型提示规范,在目前的条件下,并且很可能未来版本中长期存在的一个问题是,对于包内循环导入,一些类型可能无法获得类实例,而只能获得包含类名的字符串。进行类型判断,从功能性角度讲理应可以向上递归,即如果定义输入类型为A 类,那么输入 A 类和其子类都是可以接受的,这种情况下需要进行 isinstance 判断,类实例进行这种判断很容易实现,字符串实现起来比较困难。

    其二是如何引入检查的问题。用户自行使用装饰器修改函数的话可以自然地引入检查,但如果要用类似命令行启动的方式,实际上在做的是检查程序接管控制权,hack 进入程序当中,将所有 runtime 运行的实例进行某种替换,以实现执行前和执行后的输入输出检查。我个人技术比较低微,不知道这种接管有没有可能实现,简单想了一下没什么好的办法,各位提提意见。

    6 条回复    2021-01-29 02:07:07 +08:00
    caviar
        1
    caviar  
       2021-01-27 20:23:42 +08:00
    说实话没有完全看懂。
    如果是静态检查的话,可以看下 https://github.com/python/mypy

    如果是运行时检查的话,可以看下 https://typeguard.readthedocs.io/en/latest/userguide.html
    有你说的用 decorator 的,也有用 profiler hook 的。
    LeeReamond
        2
    LeeReamond  
    OP
       2021-01-27 20:45:26 +08:00   ❤️ 1
    @caviar mypy 用过,另外还用过一个叫 pyright 的,那个不怎么样,mypy 的 ide 检查还不错,但是感觉我这个偏运行时?我研究一下你发这个 typeguard,还有 profiler hook 是啥,没听过这个词
    LeeReamond
        3
    LeeReamond  
    OP
       2021-01-28 02:53:07 +08:00   ❤️ 1
    大概调研了一下,目前感觉一个可行的实现思路是这样,首先 hook 模式对我来说难以理解,暂时认为不可行,相反装饰器模式很简单,可以通过修改装饰器修改 metaclass,实现对普通函数,和类内所有函数的手动标注,这样注入之后程序在所有函数的入口和出口处都有了类型检查,在自动测试中自然也一样。

    之后只需要在发布的时候删除装饰器就可以了,可以写一个非常简单的状态机搞定。
    shniubobo
        4
    shniubobo  
       2021-01-28 09:49:43 +08:00 via Android
    见过一个框架通过 monkey patch 标准库,在 io 操作时自动 yield,来实现并发的: https://nameko.readthedocs.io/en/stable/key_concepts.html#concurrency
    借鉴这种方法,或许可以实现在完全不修改代码的情况下测试,而不需要测试时写上装饰器、发布时删掉。
    frostming
        5
    frostming  
       2021-01-28 10:26:45 +08:00
    @LeeReamond 你这就是 mypy
    mypy main.py 就能检查

    pytest-mypy 也有
    不要总觉得没人做过,就马上要造轮子,先说说已有的方案为何不满足
    LeeReamond
        6
    LeeReamond  
    OP
       2021-01-29 02:07:07 +08:00   ❤️ 1
    @frostming mypy 的 pycharm 插件很好用,但是 runtime 我觉得很糟糕,经常卡死,异常又怪。不过刚才试了一下,之前没试过的,runtime 确实是支持 PEP563,这样说来也堪用了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   956 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 21:02 · PVG 05:02 · LAX 13:02 · JFK 16:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.