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?
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
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'
Notez également que si vous importez app
via un autre fichier Python (tel qu'un fichier de vue lorsque vous utilisez Blueprints):
Si vous importez une application de cette manière, vous obtiendrez des erreurs de peluchage sur app.logger.info
:
from myapp import app
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.