【问题标题】:How can I tell pylint that a variable will be defined at run time?如何告诉 pylint 将在运行时定义一个变量?
【发布时间】:2017-02-14 16:05:12
【问题描述】:

短版:如果我定义一个装饰器来在运行时导入一个模块并在func_globals 中声明一个方法,我如何告诉Pylint 结果变量已经定义?

长版:考虑以下示例:

from importlib import import_module

def with_import(module):
    modname = module.split('.')[-1]
    def decorate(func):
        def wrapper(*args, **kwargs):
            func.func_globals[modname] = import_module(module)
            return func(*args, **kwargs)
        return wrapper
    return decorate

@with_import('numpy')
def create_array(n):
    return numpy.empty(n)

print(create_array(5))

这段代码工作得很好,因为with_import 装饰器为create_array 函数声明了numpy。但是,当我运行 PyLint 时,我看到了

E: 16,11: Undefined variable 'numpy' (undefined-variable)

有没有办法告诉 Pylint 这个变量实际上是在运行时定义的?我真的不想禁用整个模块的unused-variable 检查,以防有人在以后实际声明一个常规未使用的变量。

【问题讨论】:

  • 你能解释一下你为什么这样做吗?真的不是很好。
  • with_import 装饰器在生产模块中用于在运行时导入可选依赖项,并带有引用调用函数的漂亮错误消息。我本可以把它放到一个函数中,然后在相关方法的第一行调用它,但是装饰器看起来更优雅(当时)。

标签: python python-decorators pylint


【解决方案1】:

您可以禁用基于块或行的检查,例如

def f():
    # pylint: disable=E0602
    x[0] = 5
    y[0] = 5
# No errors

def f():
    x[0] = 5 # pylint: disable=E0602
    y[0] = 5
# Only y will raise the undefined variable error

有了装饰器,你就有了与第一个等价的装饰器,实际上我很惊讶它的工作原理,并认为它很丑但是:

@deco
# pylint: disable=E0602
def f():
    x[0] = 5 # No error here
y[0] = 5 # Error here

请注意,您将在 pylint 报告中显示 I: Locally disabling undefined-variable (E0602)

【讨论】:

  • 不幸的是,这将禁用所有未定义变量的警告。理想情况下,有一种方法可以禁用特定变量的警告。
【解决方案2】:

pylint 关注typing.TYPE_CHECKING。所以你可以这样做:

import typing
if typing.TYPE_CHECKING:
    import numpy

@with_import('numpy')
def create_array(n):
    return numpy.empty(n)

typing.TYPE_CHECKING 在运行时始终为 false,因此导入不会运行。但是,pylint 假定 typing.TYPE_CHECKING 为真,并将分析代码,就像执行了导入一样。

【讨论】:

    【解决方案3】:

    如果你的装饰器将这些模块作为参数提供给你的函数怎么办?

    这是一个工作示例:

    from importlib import import_module
    
    def with_import(module):
        modname = module.split('.')[-1]
        def decorate(func):
            def wrapper(*args, **kwargs):
                obj = import_module(module)
                func.func_globals[modname] = obj
                # merge modname=obj with kwargs
                return func(*args, **dict({modname: obj}, **kwargs))
            return wrapper
        return decorate
    
    @with_import('numpy')
    def create_array(n, numpy):
        # module available here and nobody complains
        return numpy.empty(n)
    
    print create_array(5)
    

    【讨论】:

      【解决方案4】:

      仅针对它发生的确切行禁用它:

      @with_import('numpy')
      def create_array(n):
          return numpy.empty(n) # pylint: disable=undefined-variable
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-12-23
        • 2013-06-25
        • 1970-01-01
        • 2012-03-25
        • 1970-01-01
        • 2022-10-16
        • 2011-10-20
        相关资源
        最近更新 更多