os.getenv 的 Python typehint 导致下游不兼容类型错误

Grr*_*Grr 9 python mypy python-typing

当用于os.getenv检索环境变量时,默认行为返回Optional[str]. 这是有问题的,因为使用这些变量的任何下游方法/函数都可能被定义为str显式接受类型。是否有可接受的用法来解决此问题或强制执行str返回类型?

getenv在in typeshed的存根文件定义中,您可以发现它的getenv返回类型可以为Optional[str]或 ,Union[str, T_]具体取决于 kwarg 的使用default

目前我能看到的四个选项是:

  1. 定义任何下游操作以接受Optional[str]类型作为参数。这感觉不太正确,因为函数/方法的结构可能不符合类型的Optional意义。即该操作没有理由将特定参数设为None
  2. 使用defaultkwarg forgetenv并提供str默认值。这似乎更正确,但要求为每次使用设置一个默认值getenv。我能看到的唯一问题是这样做可能会混淆不同环境中的测试或使用。
  3. 定义某种变量检查函数。这可能是一个函数,它接受要加载的环境变量的名称,显式返回一个字符串,并在环境变量不存在时引发错误。
  4. 显式设置返回值的类型为getenvstr。我真的不喜欢这个,因为它期望环境始终被正确配置,根据我的经验,这不是一个好的假设。

下面是一个引发 mypy 错误的示例。

import os

SOME_VAR = os.getenv("SOME_VAR")


def some_func(val: str) -> None:
    print(f"Loaded env var: {val}")


some_func(SOME_VAR)
Run Code Online (Sandbox Code Playgroud)

上面引发了 mypy 错误:

错误:“some_func”的参数 1 具有不兼容的类型“Optional[str]”;预期“str”

Ant*_*ile 12

tl;dros.environ['SOME_VAR']如果您确定它始终存在,请使用


os.getenv可以并且确实返回None- mypy 有助于向您显示那里有一个错误:

>>> repr(os.getenv('DOES_NOT_EXIST'))
'None'
>>> repr(os.getenv('USER'))
"'asottile'"
Run Code Online (Sandbox Code Playgroud)

或者,您可以通过两种不同的方式让 mypy相信它是您期望的类型:

  1. 使用断言:
>>> repr(os.getenv('DOES_NOT_EXIST'))
'None'
>>> repr(os.getenv('USER'))
"'asottile'"
Run Code Online (Sandbox Code Playgroud)
  1. 使用演员表:

    x = os.getenv('SOME_VAR')
    assert x is not None, x
    # mypy will believe that it is non-None after this point
    
    Run Code Online (Sandbox Code Playgroud)

(强制转换有一些缺点,因为它永远不会被检查,而断言有望导致测试失败)

我建议不要忽略这个错误/解决它,而是用于os.environ['SOME_VAR']您期望始终存在的东西,或者编写一个条件来检查丢失的错误情况

  • 这对我来说最有意义。我想我对“getenv”很着迷,因为我一直在使用 dot_env 文件,甚至没有想到“environ”。我更喜欢允许也允许的快速失败方法。 (2认同)