Ложное срабатывание Pylint для приложения Flask app.logger: E1101: метод 'logger' не имеет члена 'debug' (без члена)

Использование функций-членов app.logger flask (таких как app.logger.error) заставляет pylint сообщать об ошибках E1101 (no-member), даже если эти элементы app.logger определены во время выполнения.

Это можно воспроизвести с помощью следующих файлов:

app.py

import flask
app = flask.Flask(__name__)

@app.route('/')
def say_hello():
    app.logger.debug('A debug message')
    app.logger.error('An error message')
    return 'hello'

requirements.txt

pylint==2.1.0
Flask==1.0.2

Примеры команд для воспроизведения проблемы с использованием virtualenv:

(Здесь используется Python 3.5, но проблема не связана с этой версией)

virtualenv --python=python3.5 env
source env/bin/activate
pip install pip==18.0
pip install -r requirements.txt

И, наконец, запускаем pylint:

pylint -E app

Возвращает эти ошибки:

************* Module app
app.py:9:4: E1101: Method 'logger' has no 'debug' member (no-member)
app.py:10:4: E1101: Method 'logger' has no 'error' member (no-member)

Есть ли хороший способ избежать этих ложных срабатываний?


person Odysseas    schedule 03.08.2018    source источник
comment
отчет об ошибке pylint: github.com/PyCQA/pylint/issues/2586   -  person sebas    schedule 30.04.2020


Ответы (3)


Вместо этого используйте create_logger.

from flask import Flask
from flask.logging import create_logger

APP = Flask(__name__)
LOG = create_logger(APP)


@APP.route('/')
def say_hello():
    LOG.debug('A debug message')
    LOG.error('An error message')
    return 'hello'
person Yan QiDong    schedule 13.12.2018

Решение для предотвращения этих ложных срабатываний с помощью плагинов pylint:

pylintplugins.py

import sys

from astroid import MANAGER, scoped_nodes, extract_node
from astroid.builder import AstroidBuilder


def register(_linter):
    pass


def transform(f):
    if f.name == 'logger':
        for prop in ['debug', 'info', 'warning', 'error', 'addHandler']:
            f.instance_attrs[prop] = extract_node('def {name}(arg): return'.format(name=prop))


MANAGER.register_transform(scoped_nodes.FunctionDef, transform)

Этот обходной путь предотвращает ошибки линтинга на app.logger.debug, app.logger.info, app.logger.warning, app.logger.error и app.logger.addHandler.

Для использования файл pylintplugins.py необходимо загрузить с помощью параметра командной строки --load-plugins:

PYTHONPATH="." pylint -E app --load-plugins pylintplugins

или включив следующую строку в файл конфигурации pylintrc:

load-plugins=pylintplugins
person Odysseas    schedule 03.08.2018

Также обратите внимание, что если вы импортируете app через другой файл Python (например, файл представления при использовании Blueprints):

  1. Если вы импортируете такое приложение, вы получите ошибку lint на app.logger.info:

    from myapp import app

  2. Если вы импортируете такое приложение, вы не получите ошибок lint на app.logger.info:

    from flask import current_app as app

Из документации:

Flask решает эту проблему с помощью контекста приложения. Вместо того, чтобы обращаться к приложению напрямую, вы используете прокси current_app, который указывает на приложение, обрабатывающее текущую активность.

У меня нет точного ответа на вопрос, почему, но у меня это работает, когда я использую pylint==2.2.2 на python3.6.6. Как всегда, ваш пробег может отличаться.

person Niklas B    schedule 05.12.2018