Python 为包含常量的模块键入提示

Python 为包含常量的模块键入提示,python,pyright,Python,Pyright,我有一个config.py文件,其中有一个常量列表,例如: config.py NAME = 'John' AGE = 23 在另一个文件中,我将此文件作为模块导入,然后将其作为参数传递给其他函数。我使用ModuleType作为这个参数的类型 import config from types import ModuleType def f1(config: ModuleType) -> None: print(config.NAME) 问题是,当我运行pyright linte

我有一个config.py文件,其中有一个常量列表,例如:

config.py
NAME = 'John'
AGE = 23
在另一个文件中,我将此文件作为模块导入,然后将其作为参数传递给其他函数。我使用ModuleType作为这个参数的类型

import config
from types import ModuleType
def f1(config: ModuleType) -> None:
    print(config.NAME)
问题是,当我运行pyright linter时,它会报告一个错误:

 79:30 - error: Cannot access member "NAME" for type "ModuleType"
    Member "NAME" is unknown (reportGeneralTypeIssues)

输入配置提示以避免这些错误的正确方法是什么?谢谢大家!

事实证明,所有模块都是
类型.ModuleType
的子类型,因此
类型.ModuleType
。因此,您想要的是:

def f1(config: config) -> None:
    print(config.NAME)
第一个
config
只是一个形式参数,第二个按名称引用模块。
输入
模块将实际导入成员,并且一切正常


这确实让我想知道这有什么意义。如果必须导入模块才能定义函数,那么为什么要将其作为参数传递呢?

到目前为止,最简单、最方便的处理方法就是不注释
config
参数,或者将其注释为
Any
。您可以提供更具体的注释,但它会变得非常尴尬

现有注释的问题是,
f1
被注释为将任意模块作为参数,并且任意模块可能没有
NAME
属性。(另外,
ModuleType
位于
types
中,而不是
typing
)f1的正确、特定注释将指定它采用具有
名称
属性的内容,您可以使用自定义协议类指定该属性:

import typing

class HasName(typing.Protocol):
    NAME: str

def f1(config: HasName) -> None:
    print(config.NAME)
但是您必须在
config
中定义所有您想要定义的内容,如果您想要在
config
中允许可选的配置定义,那么这将变得更加尴尬

此外,如果您试图将<代码> CONFIG <代码>作为一个参数到F1,它仍然不能工作,因为当您传递一个模块作为参数时,MyPy将其视为一个通用模块,而不考虑其内容。(我不知道pyright做什么,但mypy就是这样处理的。)您必须显式地强制转换

config

f1(typing.cast(HasName, config))

这是非常尴尬的。另外,一旦你有了这个强制转换,即使
config
没有
NAME
属性,mypy也不会报告错误,所以你从所有这些笨拙的工作中根本得不到安全。

不,模块是
类型的实例。ModuleType
,而不是子类型。模块不是类型。如果尝试将模块指定为类型,mypy
错误:模块“whatever”作为类型无效。好的,我知道我在试验时出错的地方了。我包含的代码可以运行,但不正确。也许我应该把它作为一个坏例子。我试图重新创建它以进行测试,但我在任何地方都找不到typing.ModuleType。我也看过文件,但也没有。你是怎么得到你的?因为打字时没有
ModuleType
<代码>从类型导入模块类型
。从
types
@12944qwerty导入
ModuleType
后,我没有发现任何问题是的,应该是
types
而不是
types
@m.I.cosacak是的,我发现了很多。但不知怎的OP能从打字中得到它。。。除非linter没有意识到ModuleType不是通过键入来实现的。OP是用python运行该文件还是仅仅通过linter运行该文件?嗯,我刚刚通过导入
类型
测试了这一点,它似乎可以工作。我认为这个问题可以通过一个排版修正来回答,对吗?将类型设置为任何类型似乎都解决了这个问题。非常感谢。