Mypy无法在Python3 Django App中找到所有模块

Posted

技术标签:

【中文标题】Mypy无法在Python3 Django App中找到所有模块【英文标题】:Mypy Cannot Find All Modules in Python3 Django App 【发布时间】:2019-02-13 19:04:10 【问题描述】:

背景

我在一个使用 Mypy 进行类型检查的大型 Python3 存储库中工作。按照PEP420我们不使用__init__.py文件。

Mypy 最近添加了对隐式命名空间包的支持,但现在的实现遵循来自给定入口点的import 语句链。在这个 repo 的情况下,(一个 Django 应用程序)有许多模块是动态导入的(如中间件)或根本不导入的(测试和一次性脚本)。

考虑这个例子:

my-py3-repo/
├── hello/
│   ├── services/
│   │   └── hello_service.py
│   └── hello.py
├── scripts/
│   ├── db/
│   │   └── migrate.py
│   └── manage.py
└── tests/
    └── hello/
        ├── services/
        │   └── hello_service_test.py
        └── hello_test.py

假设hello.py 导入hello_service.pyhello 命名空间下的所有内容都将按预期使用mypy ./hello 进行类型检查。

问题

但是,pytestnosedjango 等的测试发现的工作方式不同,hello_test.py 通常不会导入 hello_service_test.py。 Mypy 目前无法通过mypy ./tests 发现hello_service_test.py(如果不使用__init__.py)。

同样,scripts 目录下的所有内容都会遇到同样的问题。

问题

如何配置 Mypy 以便始终对 scriptstests 目录进行类型检查?

配置

# Pipfile
[dev-packages]
mypy = "==0.670"
[requires]
python_version = "3.7"
# setup.cfg
[mypy]
python_version = 3.7
ignore_missing_imports = True
namespace_packages = True

另请参阅我在 Mypy 存储库中创建的 this issue。

【问题讨论】:

【参考方案1】:

这不能仅在 Mypy 中解决,但这里有一些有用的解决方法:

1.在 Bash 中循环文件

简单版:

find . -iname '*.py' ! -name '__init__.py' | xargs mypy

但是,如果任何两个文件具有相同的名称,这将失败(因为 Mypy 尝试将它们都作为***模块导入)。根据您的目录结构,您可以通过循环共享模块名称的单独应用程序/服务来解决此问题:

for dir in ./myapp/*/;
    do find $dir%*/ -iname '*.py' ! -name '__init__.py'\
    | xargs pipenv run mypy;
done

改编自this answer

...当然,如果您需要它以错误代码退出,您必须自己接线:


EXIT_STATUS=0
for dir in ./myapp/*/;
    do find $dir%*/ -iname '*.py' ! -name '__init__.py'\
    | xargs pipenv run mypy;
    if [ $$? -eq 1 ]; then EXIT_STATUS=1; fi; \
done;
exit $EXIT_STATUS;

2。只需使用初始化文件

放弃并将__init__.py文件放在Mypy通过import链找不到的任何模块旁边。

我已向 Mypy 存储库提交了 feature request 请求 --recursive 选项(或类似选项),该选项将指示 Mypy 键入检查给定目录及其子目录下的 .py 文件.

希望这个答案将在可用时使用更好的解决方案进行更新。

【讨论】:

以上是关于Mypy无法在Python3 Django App中找到所有模块的主要内容,如果未能解决你的问题,请参考以下文章

使用 Mypy 本地存根

尝试启动应用程序时无法导入 Django 错误

使用 mypy 进行类型检查,我无法弄清楚为啥会发生此错误 [关闭]

在 VS Code 中安装 mypy 的问题

如何为 Mypy 类型注释指定 OrderedDict K,V 类型?

mypy 无法识别从超类继承的变量