如何在我的代码中传递全局调试标志变量;我应该使用 argparse 吗?
How to pass global debug flag variable throughout my code; should I use argparse?
假设我有一个主程序 (test.py) 和一个小实用程序 (test_utils.py),它具有由主程序调用的辅助函数。
我想通过传递 debug_flag
布尔值来打开代码中的调试语句,该布尔值通过 argparse
.
读取
现在我希望我的 test_utils.py
程序中的函数也根据 debug_flag
的值打印调试语句。我总是可以将 debug_flag
作为参数添加到 test_utils.py
中的每个函数定义中,并在调用函数时传递参数,但是这里有更好的方法吗,比如使 debug_flag
成为全局变量?但是如果我从 test.py
声明 debug_flag
是全局的,那将如何导入到 test_utils.py
?
这里最elegant/Pythonic的方法是什么?
test.py:
import argparse
from test_utils import summation
def main():
args = get_args()
debug_flag = True if args[debug] == 'True' else False
print summation(5, 6, 7)
def get_args():
parser = argparse.ArgumentParser(description='Test program')
parser.add_argument('-d','--debug', help='Debug True/False', default=False)
args = vars(parser.parse_args())
return args
test_utils.py:
from test import debug_flag
def summation(x, y, z):
if debug_flag:
print 'I am going to add %s %s and %s' % (x, y, z)
return x + y + z
EDIT1:澄清 - 如果我通过 argparse 传递调试标志,从而将 debug_flag 设置为 True - 这将如何传播到 test_utils.py
中的函数?
EDIT2:根据@joran-beasley 的建议,这就是我得到的。
test.py:
import argparse
import logging
from test_utils import summation
def main():
args = get_args()
logging.getLogger("my_logger").setLevel(logging.DEBUG if args['debug'] == 'True' else logging.WARNING)
print summation(5, 6, 7)
def get_args():
parser = argparse.ArgumentParser(description='Test program')
parser.add_argument('-d','--debug', help='Debug True/False', required=True)
args = vars(parser.parse_args())
return args
main()
test_utils.py
import logging
log = logging.getLogger('my_logger')
def summation(x, y, z):
log.debug('I am going to add %s %s and %s' % (x, y, z))
return x + y + z
当我 运行 test.py 时,我得到:
$ python test.py -d True
No handlers could be found for logger "my_logger"
18
使用日志记录
# this logger will always now be logging.DEBUG level
logging.getLogger("my_logger").setLevel(logging.DEBUG if args.debug else logging.WARNING)
然后使用
log = logging.getLogger("my_logger")
...
log.warn("some text that should always be seen!")
log.debug("some debug info!")
然后您可以在具有多个日志记录级别的地方执行操作
log_level = logging.WARNING
if args.verbose > 0:
log_level = logging.INFO
elif args.verbose > 3:
log_level = logging.DEBUG
如果出于某种原因您需要检索 currentEffectiveLogLevel(在大多数情况下您真的不应该...当您需要调试级别输出时只需使用 log.debug
)
logging.getLogger("my_logger").getEffectiveLevel()
[编辑澄清]
log = logging.getLogger('my_logger')
def summation(x, y, z):
log.debug('I am going to add %s %s and %s' % (x, y, z)) # will not print if my_logger does not have an effective level of debug
return x + y + z
print(summation(2, 3, 4))
log.setLevel(logging.DEBUG)
print(summation(4, 5, 6))
或者你可以写一个辅助函数
def is_debug():
return logging.getLogger("my_logger").getEffectiveLevel() == logging.DEBUG
当然,你总是可以做一些可怕的骇人听闻的废话,比如将它写入一个平面文件并读取它或使用真正的全局变量(比你想象的更难,还有很多边缘情况需要担心)
您可以通过传递一个可变变量在 Python 中实现 "package-wide" 全局。在这些情况下,我最喜欢的方法是创建自定义 Flags
class。然后,您在所有模块之间共享 Flags
的一个实例,其属性的功能类似于全局变量。这是您发布的代码的示例:
test_utils.py
__all__ = ['flags', 'summation']
class Flags(object):
def __init__(self, *items):
for key,val in zip(items[:-1], items[1:]):
setattr(self,key,val)
flags = Flags('debug', False)
def summation(x, y, z):
if flags.debug:
print 'I am going to add %s %s and %s' % (x, y, z)
return x + y + z
test.py
#!/usr/bin/env python2
import argparse
import sys
from test_utils import summation, flags
def main():
args = get_args()
flags.debug = args['debug']
print summation(5, 6, 7)
def get_args():
parser = argparse.ArgumentParser(description='Test program')
parser.add_argument('-d','--debug', action='store_true', help='Debug True/False', default=False)
args = vars(parser.parse_args())
return args
if __name__=='__main__':
main()
我将标志移动到 test_utils.py 以避免循环导入问题,但这应该不会影响任何事情。一个更强大的解决方案(适用于较大的项目)将有一个单独的 config.py (或其他)模块,其中 flags
被初始化。
简单的回答。在主文件中分配一个字典。然后通过所有其他模块导入它。
Test.py
debug_flag = {'setting' : False}
test_utils.py
from test import debug_flag
def print_flag():
print(debug_flag['setting'])
def set_flag(setting):
debug_flag['setting'] = setting
set_flag(True)
print_flag()
现在,无论何时您从主模块导入 debug_flag,一旦您处理了 arg 解析,它就会具有您设置标志的任何设置。然后您可以随时更改此设置,后续调用将获取更改。
假设我有一个主程序 (test.py) 和一个小实用程序 (test_utils.py),它具有由主程序调用的辅助函数。
我想通过传递 debug_flag
布尔值来打开代码中的调试语句,该布尔值通过 argparse
.
现在我希望我的 test_utils.py
程序中的函数也根据 debug_flag
的值打印调试语句。我总是可以将 debug_flag
作为参数添加到 test_utils.py
中的每个函数定义中,并在调用函数时传递参数,但是这里有更好的方法吗,比如使 debug_flag
成为全局变量?但是如果我从 test.py
声明 debug_flag
是全局的,那将如何导入到 test_utils.py
?
这里最elegant/Pythonic的方法是什么?
test.py:
import argparse
from test_utils import summation
def main():
args = get_args()
debug_flag = True if args[debug] == 'True' else False
print summation(5, 6, 7)
def get_args():
parser = argparse.ArgumentParser(description='Test program')
parser.add_argument('-d','--debug', help='Debug True/False', default=False)
args = vars(parser.parse_args())
return args
test_utils.py:
from test import debug_flag
def summation(x, y, z):
if debug_flag:
print 'I am going to add %s %s and %s' % (x, y, z)
return x + y + z
EDIT1:澄清 - 如果我通过 argparse 传递调试标志,从而将 debug_flag 设置为 True - 这将如何传播到 test_utils.py
中的函数?
EDIT2:根据@joran-beasley 的建议,这就是我得到的。
test.py:
import argparse
import logging
from test_utils import summation
def main():
args = get_args()
logging.getLogger("my_logger").setLevel(logging.DEBUG if args['debug'] == 'True' else logging.WARNING)
print summation(5, 6, 7)
def get_args():
parser = argparse.ArgumentParser(description='Test program')
parser.add_argument('-d','--debug', help='Debug True/False', required=True)
args = vars(parser.parse_args())
return args
main()
test_utils.py
import logging
log = logging.getLogger('my_logger')
def summation(x, y, z):
log.debug('I am going to add %s %s and %s' % (x, y, z))
return x + y + z
当我 运行 test.py 时,我得到:
$ python test.py -d True
No handlers could be found for logger "my_logger"
18
使用日志记录
# this logger will always now be logging.DEBUG level
logging.getLogger("my_logger").setLevel(logging.DEBUG if args.debug else logging.WARNING)
然后使用
log = logging.getLogger("my_logger")
...
log.warn("some text that should always be seen!")
log.debug("some debug info!")
然后您可以在具有多个日志记录级别的地方执行操作
log_level = logging.WARNING
if args.verbose > 0:
log_level = logging.INFO
elif args.verbose > 3:
log_level = logging.DEBUG
如果出于某种原因您需要检索 currentEffectiveLogLevel(在大多数情况下您真的不应该...当您需要调试级别输出时只需使用 log.debug
)
logging.getLogger("my_logger").getEffectiveLevel()
[编辑澄清]
log = logging.getLogger('my_logger')
def summation(x, y, z):
log.debug('I am going to add %s %s and %s' % (x, y, z)) # will not print if my_logger does not have an effective level of debug
return x + y + z
print(summation(2, 3, 4))
log.setLevel(logging.DEBUG)
print(summation(4, 5, 6))
或者你可以写一个辅助函数
def is_debug():
return logging.getLogger("my_logger").getEffectiveLevel() == logging.DEBUG
当然,你总是可以做一些可怕的骇人听闻的废话,比如将它写入一个平面文件并读取它或使用真正的全局变量(比你想象的更难,还有很多边缘情况需要担心)
您可以通过传递一个可变变量在 Python 中实现 "package-wide" 全局。在这些情况下,我最喜欢的方法是创建自定义 Flags
class。然后,您在所有模块之间共享 Flags
的一个实例,其属性的功能类似于全局变量。这是您发布的代码的示例:
test_utils.py
__all__ = ['flags', 'summation']
class Flags(object):
def __init__(self, *items):
for key,val in zip(items[:-1], items[1:]):
setattr(self,key,val)
flags = Flags('debug', False)
def summation(x, y, z):
if flags.debug:
print 'I am going to add %s %s and %s' % (x, y, z)
return x + y + z
test.py
#!/usr/bin/env python2
import argparse
import sys
from test_utils import summation, flags
def main():
args = get_args()
flags.debug = args['debug']
print summation(5, 6, 7)
def get_args():
parser = argparse.ArgumentParser(description='Test program')
parser.add_argument('-d','--debug', action='store_true', help='Debug True/False', default=False)
args = vars(parser.parse_args())
return args
if __name__=='__main__':
main()
我将标志移动到 test_utils.py 以避免循环导入问题,但这应该不会影响任何事情。一个更强大的解决方案(适用于较大的项目)将有一个单独的 config.py (或其他)模块,其中 flags
被初始化。
简单的回答。在主文件中分配一个字典。然后通过所有其他模块导入它。
Test.py
debug_flag = {'setting' : False}
test_utils.py
from test import debug_flag
def print_flag():
print(debug_flag['setting'])
def set_flag(setting):
debug_flag['setting'] = setting
set_flag(True)
print_flag()
现在,无论何时您从主模块导入 debug_flag,一旦您处理了 arg 解析,它就会具有您设置标志的任何设置。然后您可以随时更改此设置,后续调用将获取更改。