フラスコのapp.logger
メンバー関数(app.logger.error
など)を使用すると、E1101
のメンバーであってもpylint
が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)
これらの誤検知を回避する良い方法はありますか?
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
のlintingエラーを防ぎます。
pylintplugins.pyファイルを使用するには、--load-plugins
コマンドラインオプションを使用してロードする必要があります。
PYTHONPATH="." pylint -E app --load-plugins pylintplugins
または、pylintrc
構成ファイルに次の行を含めることによって:
load-plugins=pylintplugins
使用する 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'
また、別のpythonファイル(ブループリントを使用する場合のビューファイルなど))を介してapp
をインポートする場合も注意してください。
このようなアプリをインポートすると、app.logger.info
でlintエラーが発生します。
from myapp import app
このようなアプリをインポートすると、app.logger.info
でlintエラーが発生しなくなります。
from flask import current_app as app
ドキュメント から:
Flaskはアプリケーションコンテキストでこの問題を解決します。アプリを直接参照するのではなく、現在のアクティビティを処理するアプリケーションを指すcurrent_appプロキシを使用します。
理由はわかりませんが、pylint==2.2.2
でpython3.6.6
を使用するとうまくいきます。いつものように、あなたの距離は変わるかもしれません。