web-dev-qa-db-fra.com

Pylint faux positif pour "app.logger" de Flask: E1101: La méthode 'logger' n'a pas de membre 'debug' (pas de membre)

L'utilisation des fonctions membres app.logger du flacon (telles que app.logger.error) force pylint à signaler des erreurs E1101 (no-member), même si ces membres de app.logger sont définis à l'exécution.

Ceci peut être reproduit en utilisant les fichiers suivants:

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

Exemples de commandes permettant de reproduire le problème, à l'aide de virtualenv:

(Python 3.5 est utilisé ici, mais le problème n'est pas spécifique à cette version)

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

Et enfin, en exécutant pylint:

pylint -E app

Renvoie ces erreurs:

************* 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)

Existe-t-il un bon moyen d'éviter ces faux positifs?

4
Odysseas

Une solution pour éviter ces faux positifs, via les plugins 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)

Cette solution de contournement évite les erreurs de peluchage sur app.logger.debug, app.logger.info, app.logger.warning, app.logger.error et app.logger.addHandler.

Pour être utilisé, le fichier pylintplugins.py doit être chargé à l'aide de l'option --load-plugins en ligne de commande:

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

ou en incluant la ligne suivante dans le fichier de configuration pylintrc:

load-plugins=pylintplugins
2
Odysseas

Utilisez create_logger à la place.

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'
1
Yan QiDong

Notez également que si vous importez app via un autre fichier Python (tel qu'un fichier de vue lorsque vous utilisez Blueprints):

  1. Si vous importez une application de cette manière, vous obtiendrez des erreurs de peluchage sur app.logger.info:

    from myapp import app

  2. Si vous importez une application de cette manière, vous ne recevrez pas d'erreurs de peluchage sur app.logger.info:

    from flask import current_app as app 

De la documentation :

Flask résout ce problème avec le contexte de l'application. Plutôt que de faire directement référence à une application, vous utilisez le proxy current_app, qui pointe vers l'application qui gère l'activité en cours.

Je ne sais pas trop pourquoi, mais cela fonctionne pour moi en utilisant pylint==2.2.2 sur python3.6.6. Comme toujours, votre kilométrage peut varier. 

0
Niklas B