用 mypy 检查 Python 类型系统

作者: , 共 13338 字 , 共阅读 0

类型系统可以提前检查代码准确性,为中大型项目提供保障。所以现在大型编程语言都争先恐后地为程序添加类型系统。

1、安装 mypy

首先安装 mypy

sudo -E pip3 install mypy 

其次,大多数包都有配套的stub包,一般为{package}-stub。下面脚本可以为系统库一次性全部安装对应的 stub 库:

import os
import pkg_resources

installed_packages = list(pkg_resources.working_set)
installed_packages_list = sorted([f"{i.key}=={i.version}" for i in installed_packages])
installed_packages_list = [i.split('==')[0] for i in installed_packages_list]

installed_packages_list = [i for i in installed_packages_list if not i.endswith("-stubs")]

installed_stubs = []

# Try to install stubs for each package
for package_name in installed_packages_list:
    try:
        # Attempt to install the stubs package
        os.system(f"sudo -E pip3 install -U types-{package_name}  {package_name}-stubs {package_name}-stub")
        installed_stubs.append(package_name)
    except Exception as e:
        print(f"No stubs found for {package_name}: {e}")

print(f"系统一共安装了{len(installed_packages_list)}个库,"
       f"已安装{len(installed_stubs)}个类型库:{installed_stubs}")

2、配置 vim

直接在 linters 里为 python 添加 mypy 即可,可以和 pylint 同时使用:

Plug 'w0rp/ale'
let g:ale_linters = {'cpp': [], 'c': [], 'python': ['pylint', 'mypy', ], 'javascript': ['eslint', ], 'vue': ['eslint', ],  } 

3、配置 mypy

首先一个最重要的: mypy 不会自动使用 PYTHONPATH 的环境变量。所以自己的库需要手工添加到 MYPY 里。在你的~.bashrc或者~/.zshrc(根据你使用什么 bash 环境)添加环境变量:

export MYPYPATH=$HOME/your_local_path:/opt/other_path
# or
export MYPYPATH=$PYTHONPATH

其次,有些常用库不提供 stub , mypy 会有下面import-untyped类似的提示:

Skipping analyzing "rest_framework": module is installed, but missing library stubs or py.typed marker  [import-untyped]

这时候有两种方法,一种临时的方法是在该行代码后面添加注释取消检查:

import rest_framework # type: ignore

还有一种方法是对项目或者所有文件生效:将下面配置放在项目下的 pyproject.toml或者个人目录下的~/mypy.ini

[tool.mypy]
# The mypy configurations are set here
python_version = "3.8"
check_untyped_defs = true
ignore_missing_imports = false
warn_redundant_casts = true
warn_unused_ignores = true
warn_return_any = true

[tool.mypy-tensorflow.*]
ignore_missing_imports = true

下面这些库有类型库:

['absl-py', 'aiohttp-jinja2', 'aiohttp', 'aiosignal', 'alabaster', 'amqp', 'ansi2html', 'anyio', 'appdirs-stubs', 'appdirs', 'argcomplete', 'argon2-cffi', 'arrow', 'asgiref', 'astroid', 'asttokens', 'astunparse', 'async-generator', 'async-timeout', 'asyncssh', 'atomicwrites', 'attrs', 'automat', 'autopep8', 'babel', 'backcall', 'backports.zoneinfo', 'bcrypt', 'beautifulsoup4', 'billiard', 'binaryornot', 'black', 'bleach', 'blinker', 'bottle', 'brlapi', 'brotli', 'cached-property', 'cachetools', 'celery-stubs', 'celery', 'certifi', 'cffi', 'chardet', 'charset-normalizer', 'cheat', 'click-didyoumean', 'click-plugins', 'click-repl', 'click', 'clickhouse-connect', 'cloudpickle', 'colorama', 'coloredlogs', 'colorlog', 'comm', 'command-not-found', 'constantly', 'contourpy', 'cookiecutter', 'cppman', 'cryptography', 'cssselect', 'cupshelpers', 'cvxopt', 'cx-oracle', 'cycler', 'dataclasses-json', 'dataclasses', 'dbus-python', 'deap', 'debugpy', 'decorator', 'defer', 'defusedxml', 'diff-match-patch', 'dill', 'distro', 'django-appconf', 'django-celery-beat', 'django-celery-results', 'django-classy-tags', 'django-cors-headers', 'django-filter-stubs', 'django-filter', 'django-js-asset', 'django-model-utils', 'django-mptt', 'django-nyt', 'django-redirect-urls', 'django-sekizai', 'django-stubs-ext', 'django-stubs', 'django-timezone-field', 'django-widget-tweaks', 'django', 'djangorestframework-stubs', 'djangorestframework', 'dlib', 'dnspython', 'docker-compose', 'docker-stubs', 'docker', 'dockerpty', 'docopt', 'docstring-to-markdown', 'docutils-stubs', 'docutils', 'dolphindb', 'doxypypy', 'duplicity', 'editorconfig', 'entrypoints', 'et-xmlfile', 'exceptiongroup', 'executing', 'exifread', 'face-recognition-models', 'face-recognition', 'fasteners', 'feedgenerator', 'feedparser', 'filelock', 'flake8', 'flask', 'flatbuffers', 'fonttools', 'frozenlist', 'future', 'gast', 'ghp-import', 'glances', 'google-auth-oauthlib', 'google-auth', 'google-pasta', 'greenlet', 'grpcio', 'h11', 'h2', 'h5py', 'hpack', 'html5lib', 'httplib2', 'huggingface-hub', 'humanfriendly', 'hyperframe', 'hyperlink', 'icdiff', 'idna', 'imagesize', 'importlib-metadata', 'importlib-resources', 'imutils', 'incremental', 'inflection', 'influxdb', 'intervaltree', 'iotop', 'ipykernel', 'ipython-genutils', 'ipython', 'ipywidgets', 'isort', 'itchat', 'itemadapter', 'itemloaders', 'itsdangerous', 'jedi', 'jellyfish', 'jieba', 'jinja2-time', 'jinja2', 'jmespath', 'joblib', 'jsbeautifier', 'jsonschema', 'jupyter-client', 'jupyter-console', 'jupyter-core', 'jupyter', 'jupyterlab-pygments', 'keras-preprocessing', 'keras', 'keyring', 'kiwisolver', 'kombu', 'langchain', 'language-selector', 'lazr.uri', 'lazy-object-proxy', 'livereload', 'llama-index', 'lockfile', 'loguru', 'louis', 'lunr', 'lxml-stubs', 'lxml', 'lz4', 'macaroonbakery', 'mako', 'markdown-cjk-spacing', 'markdown-include', 'markdown-it-py', 'markdown', 'markupsafe', 'marshmallow-enum', 'marshmallow', 'matplotlib-inline', 'matplotlib', 'mccabe', 'mdurl', 'mergedeep', 'mistune', 'mkdocs-get-deps', 'mkdocs-mermaid2-plugin', 'mkdocs', 'monotonic', 'more-itertools', 'mosek', 'msgpack', 'multidict', 'mypy-extensions', 'mypy', 'nbclient', 'nbconvert', 'nbformat', 'nest-asyncio', 'netifaces', 'nltk', 'notebook', 'numpy', 'numpydoc', 'olefile', 'onboard', 'openai', 'openapi-schema-pydantic', 'opencv-python', 'openpyxl', 'openutilslitecitics', 'opt-einsum', 'ordered-set', 'outcome', 'packaging', 'padme', 'pandas-stubs', 'pandas', 'pandocfilters', 'paramiko', 'parsel', 'parso', 'pathlib', 'pathspec', 'pathtools', 'peewee', 'pelican', 'pexpect', 'pickleshare', 'pillow', 'pip', 'platformdirs', 'plot', 'pluggy', 'ply', 'poyo', 'priority', 'progressbar', 'prometheus-client', 'prompt-toolkit', 'protego', 'protobuf', 'psutil', 'psycopg2-binary', 'ptyprocess', 'pure-eval', 'pyasn1-modules', 'pyasn1', 'pycairo', 'pycodestyle', 'pycparser', 'pycrypto', 'pycryptodome', 'pycryptodomex', 'pycups', 'pycurl', 'pydantic', 'pydispatcher', 'pydocstyle', 'pyexif', 'pyflakes', 'pygments', 'pygobject', 'pyjwt', 'pylint-venv', 'pylint', 'pyls-black', 'pyls-spyder', 'pymacaroons', 'pymdown-extensions', 'pymssql', 'pymupdf', 'pymysql', 'pynacl', 'pyopenssl', 'pyparsing', 'pypdf2', 'pypinyin', 'pypng', 'pypyodbc', 'pyqrcode', 'pyqt5-sip', 'pyqt5', 'pyqtwebengine', 'pyrfc3339', 'pyrsistent', 'pysmi', 'pysnmp', 'pysocks', 'pystache', 'python-apt', 'python-crontab', 'python-dateutil', 'python-dotenv', 'python-gnupg', 'python-jsonrpc-server', 'python-language-server', 'python-lsp-black', 'python-lsp-jsonrpc', 'python-lsp-server', 'python-markdown-math', 'python-rapidjson', 'python-slugify', 'pytoolconfig', 'pytz', 'pyxdg', 'pyyaml-env-tag', 'pyyaml', 'pyzbar', 'pyzmq', 'qdarkstyle', 'qscintilla', 'qstylizer', 'qtawesome', 'qtconsole', 'qtpy', 'queuelib', 'rapidjson', 'regex', 'reportlab', 'requestium', 'requests-file', 'requests-oauthlib', 'requests-unixsocket', 'requests', 'rich', 'rope', 'rqdatac', 'rsa', 'rtree', 'ruff', 'scikit-learn', 'scipy', 'scrapy', 'screen-resolution-extra', 'seaborn', 'secretstorage', 'selenium', 'send2trash', 'service-identity', 'setuptools', 'simplejson', 'sip', 'six', 'sklearn', 'sniffio', 'snowballstemmer', 'socks', 'sorl-thumbnail', 'sortedcontainers', 'soupsieve', 'spark-parser',
'sphinx', 'sphinxcontrib-applehelp', 'sphinxcontrib-devhelp', 'sphinxcontrib-htmlhelp', 'sphinxcontrib-jsmath', 'sphinxcontrib-qthelp', 'sphinxcontrib-serializinghtml', 'spyder-kernels', 'spyder', 'sqlalchemy', 'sqlparse', 'ssh-import-id', 'stack-data', 'system-service', 'systemd-python', 'ta-lib', 'tailer', 'tenacity', 'tensorboard-data-server', 'tensorboard-plugin-wit', 'tensorboard', 'tensorflow-estimator', 'tensorflow-gpu', 'termcolor', 'terminado', 'testpath', 'text-unidecode', 'textdistance',
'texttable', 'threadpoolctl', 'three-merge', 'tinify', 'tinycss2', 'tinycss', 'tldextract', 'tokenizers', 'toml', 'tomli', 'tomlkit', 'torch-geometric', 'torch', 'torchvision', 'tornado', 'tqdm', 'traitlets', 'transformers', 'trio-websocket', 'trio', 'twisted', 'typed-ast', 'types-beautifulsoup4', 'types-cffi', 'types-html5lib', 'types-markdown', 'types-pillow', 'types-psutil', 'types-psycopg2', 'types-pymysql', 'types-pyopenssl', 'types-pytz', 'types-pyyaml', 'types-redis', 'types-requests', 'types-setuptools', 'types-six', 'types-tqdm', 'types-urllib3', 'typing-extensions', 'typing-inspect', 'typing', 'tzdata', 'tzlocal', 'ubuntu-drivers-common', 'ubuntu-make', 'ubuntu-pro-client', 'ufw', 'ujson', 'uncompyle6', 'unidecode', 'unity-scope-calculator', 'unity-scope-chromiumbookmarks', 'unity-scope-colourlovers', 'unity-scope-devhelp', 'unity-scope-manpages', 'unity-scope-texdoc', 'unity-scope-tomboy', 'unity-scope-virtualbox', 'unity-scope-yelp', 'unity-scope-zotero', 'urllib3', 'usb-creator',
'vine', 'vnpy', 'w3lib', 'wadllib', 'wand', 'watchdog', 'watchfiles', 'wcwidth', 'webdriver-manager', 'webencodings', 'websocket-client', 'websockets', 'werkzeug', 'whatthepatch', 'wheel', 'widgetsnbextension', 'wmi', 'wrapt', 'wsproto', 'wurlitzer', 'xdis', 'xkit', 'xlrd', 'xlsxwriter', 'yapf', 'yarl', 'zhconv', 'zipp', 'zope.interface', 'zstandard']

Q. E. D.

类似文章:
IT » apt, pip, python, ubuntu
正常而言,大家都是用 pip 来安装 python 的包。但有时候无意中(通常是为安装某个特定的软件,根据软件的安装提示),会使用 apt 安装 python 包。而且其实很多包都可以通过 apt 来安装的,名字就是包名再加python3-的前缀。安装后的库以及依赖项位于/usr/lib/python3/dist-packages目录下。比如 apt 安装 requests 包:
一定要先座这一几步,否则直接用pypyodbc会爆下面错误:
IT » django
在 django 的setting.py里可以设置 debug 和 production 模式:
安装 selenium ,使用 requestium 来调用 selenium 程序更为简单,因此可一起安装:
编程 » django, requests, python
这里的 requests 是指 Python 的 requests 包。
IT » Markdown, Pelican, Mkdocs
最近写文档和写博客都开始用 markdown ,其中博客用得是Pelican,文档用Mkdocs。它们俩都用python-markdown模块来处理 markdown 文件。而这个模块支持扩展,可以大大提升 markdown 的表现力:
编程 » Python
Python 在搜索模块时,依次搜索sys.path里的位置,直到找到模块为止。下面命令可以查看当前的搜索路径:
编程 » python, requests, django
在 Python 里,我们可以用request.post提交json数据:
在写代码过程中,会定义一些变量但没有用,比如为了保持函数参数原型:
编程 » Python
在 Python 中,有时候为了获取当前运行的脚本的同目录下的另外一个文件,会这么写:
昨天我们爬了太室山,打卡五岳之一嵩山。今天我们继续爬少室山。