在 Python 3.7 中,我编写了一个 Environment
辅助类,它允许我通过反射加载操作系统环境变量。它还根据派生类中声明的类型提示,将环境变量转换为 native bool 值或元组。
它可以工作,但是 Visual Studio Code 中的 linter 给我这个问题报告:
Class
'Environment'
has no'__annotations__'
member
这是辅助类。
import os
from abc import ABC
class Environment(ABC):
@classmethod
def from_os(cls):
convert = {
bool: lambda d: d == "1",
(): lambda d: tuple(d.split(',')),
str: lambda d: d
}
values = [
convert[value](os.environ[key])
for key,value in cls.__annotations__.items()
]
return cls(*values)
同样,代码确实有效。我该怎么做才能让 Pylint 开心?也许有一种不同的方法可以迭代属性(和属性类型提示),以便在不使用 __annotations__
的情况下获得相同的结果?
我可以通过欺骗和添加 pylint 抑制提示让 linter 停止提示:
for key,value in cls.__annotations__.items() # pylint: disable=no-member
...但这不是我正在寻找的解决方案。
如果有帮助,下面是一个示例,说明如何使用我的助手类来获取任意一组环境变量:
from dataclasses import dataclass
@dataclass
class FWMonitoringEnv(Environment):
# The names of these attributes are used
# to find and load a corresponding environment variable.
# This happens when "FWMonitoringEnv.from_os()" is called.
preempt : bool
split_routes : bool
tag_key : str
vpc_summary_route : str
route_table_id : str
fw_trust_enis : ()
fw_mgmt_ips : ()
api_key_name : str
region : str
在代码的其他地方我简单地执行了这个:
env = FWMonitoringEnv.from_os()
虽然我正在做这件事,但我还想解决另一个代码卫生问题。有没有办法让我的 Environment
类强制派生类成为 @dataclass
?例如,可以使用 Python 3.7 类型提示来完成吗?
最佳答案
您可以使用 https://docs.python.org/3/library/inspect.html#inspect.signature获取所有类注释的方法。
例子
pprint(inspect.signature(cls).parameters)
mappingproxy(OrderedDict([('preempt', <Parameter "preempt: bool">),
('split_routes', <Parameter "split_routes: bool">),
('tag_key', <Parameter "tag_key: str">),
('vpc_summary_route',
<Parameter "vpc_summary_route: str">),
('route_table_id', <Parameter "route_table_id: str">),
('fw_trust_enis', <Parameter "fw_trust_enis: ()">),
('fw_mgmt_ips', <Parameter "fw_mgmt_ips: ()">),
('api_key_name', <Parameter "api_key_name: str">),
('region', <Parameter "region: str">)]))
当合并到您的代码中时,它看起来如下:
def from_os(cls):
convert = {
bool: lambda d: d == '1',
(): lambda d: tuple(d.split(',')),
str: lambda d: d
}
values = [
convert[val.annotation](os.environ[val.name])
for val in signature(cls).parameters.values()
]
return cls(*values)
我相信这是让它“真实”的更好方法:-)
关于Python环境变量通过反射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59218268/