5

I'm trying to work on my current python program being very conscious of pylint warnings, so while I realize I can simply turn off the warning, I want to be sure that there is not a more desirable solution before I do.

My current section of the code is my logging code. I have a function init() that sets up handlers and attaches them to the root logger, and a function set_console_level(level) that sets the level at which console messages are reported (DEBUG, INFO, etc..):

_CONSOLE_OUT = NONE

def init():
    """Set up the error handlers for the root logger"""
    console_out = logging.StreamHandler()
    console_out.setLevel(logging.INFO)  #Show info messages for now
    #...
    logging.root.addHandler(console_out)
    global _CONSOLE_OUT
    _CONSOLE_OUT = console_out

    #Rest of function sets up more handlers similarly
init()

def set_console_level(level):
    """Change the level at which console messages are printed"""
    assert __CONSOLE_OUT is not None #Set in init
    _CONSOLE_OUT.setLevel(level) 

As far as I could tell from my reading, this is the way to do this. The line global _CONSOLE_OUT is needed in order to write to the module-level variable. However, when I run pylint on this file I get the warning W: 15,4:init: Using the global statement. Is there a way to avoid this warning? A better way to approach this problem?

(Please don't say global _CONSOLE_OUT #pylint: disable=W**** without giving justification)

4

3 に答える 3

2

You could create it at import time:

_console_out = ConsoleHandler()

where ConsoleHandler is a factory function or your class that create and setup the handler.

于 2012-08-28T04:56:49.923 に答える
1

これは、メソッドの範囲外にアイテムを設定するための奇妙なパターンです。グローバル変数がどこから設定されているかわからないため、後で問題が発生します。

コードは、メソッドの実行順序にも依存して、コードの他の部分が依存している変数を設定します。init()これは、特にインポートするときに呼び出すのを忘れた場合に、後で問題を引き起こす可能性があります(もちろん、いつでもそれを貼り付けることができますが__init__.py、それはここでは重要ではありません)。

それらを考えると、別の方法は、クラスを作成し、クラス内に変数を設定することです(別の名前空間を指定します)。または、そのままにしておきたい場合は、Sebastianが提案したように、構成変数を返します。

複数のタプルを設定する必要がある場合は、タプルを返し、それをアンパックしてグローバル変数を作成できます。

>>> def foo():
...   return "hello","world"
...
>>> a,b = foo()
于 2012-08-28T05:13:52.790 に答える
0

One thing I thought of looking at the code (and with Burhan Khalid's answer) is that there's no reason that my init() code has to be in a function at all, since I simply mean for it to be run once when imported. I believe the only reason I originally did this was so that the handler variables wouldn't be module-level.

So instead my code could simply be

_CONSOLE_OUT = logging.StreamHandler()
_CONSOLE_OUT.setLevel(logging.INFO)  #Show info messages for now
#...
logging.root.addHandler(_CONSOLE_OUT)

#...

def set_console_level(level):
    """Change the level at which console messages are printed"""
    assert _CONSOLE_OUT is not None #Set at root
    _CONSOLE_OUT.setLevel(level)
于 2012-08-28T05:31:25.963 に答える