我在Python中使用arparse来解析命令行中的参数:
def main():
parser = argparse.ArgumentParser(usage=usage)
parser.add_argument('-v', '--verbose', dest='verbose', action='store_true')
parser.add_argument(...)
args = parser.parse_args()
我只在代码的几个地方使用对象args
。
有三种方法,调用堆栈看起来像这样
def first_level(args):
second_level()
def second_level():
third_level()
def third_level():
### here I want to add some logging if args.verbose is True
我想在third_level()
添加一些日志记录。
我不想更改方法second_level()
的签名。
如何在arg
中提供third_lelvel()
对象?
我可以将arg
存储为全局变量,但有人告诉我几年前不要在开发人员培训中使用全局变量....
处理此问题的常用方法是什么?
答案 0 :(得分:2)
将我的评论转换为答案。我建议你的third_level(..)
根本没有条件。有一些机制可以让日志记录模块处理这些 - 并且可以从这3个函数之外控制这些机制。
类似的东西:
def first_level(args):
second_level()
def second_level():
third_level()
def third_level():
logging.info("log line which will be printed if logging is at INFO level")
def main():
args = ....
#Set the logging level, conditionally
if args.verbose:
logging.basicConfig(filename='myapp.log', level=logging.INFO)
else:
logging.basicConfig(filename='myapp.log', level=logging.WARNING)
first_level(args)
答案 1 :(得分:2)
常见的模块结构如下:
imports ...
<constants>
options = {verbose=0, etc}
# alt options = argparse.Namespace(logging=False,....)
def levelone(args, **kwargs):
....
def leveltwo(...):
def levelthree(...):
<use constant>
<use options>
def parser():
p = argparse.ArgumentParser()
....
args = p.parse_args() # this uses sys.argv
if __name__=='__main__':
args = parser()
options.update(vars(args))
levelone(args)
模块的主体具有功能定义,可以由其他模块导入。如果用作脚本,则parser
将读取命令行。全局options
可用于各种state
类似参数。从某种意义上说,它们是用户或导入模块可以调整的常量。从config
文件导入的值可以具有相同的角色。
另一种常见模式是使您的函数方法成为一个类,并将args
作为对象属性传递。
class Foo():
def __init__(self, logging=False):
self.logging = logging
def levelone():
def leveltwo():
<use self.logging>
foo(args.logging).levelone()
虽然不鼓励globals
,但更多是因为它们被过度使用,并破坏了功能提供的模块性。但是Python还提供了一个module
级别的命名空间,它不仅包含函数和类。并且模块中定义的任何函数都可以访问该命名空间 - 除非它自己的定义会影响它。
var1 = 'module level variable'
var2 = 'another'
def foo(var3):
x = var1 # read/use var1
var2 = 1 # shadow the module level definition
etc
=====
我不确定是否应该推荐这个,但您可以在sys.argv
内解析third_level
。
def third_level():
import argparse
p = argparse.ArgumentParser()
p.add_argument('-v','--verbose',action='count')
args = p.parse_known_args()
verbose = args.verbose
<logging>
argparse
导入sys
并使用sys.argv
。无论是在脚本级别,main
还是某些嵌套函数中使用它,都可以执行此操作。 logging
做同样的事情。您可以使用自己的导入模块将值隐式传递给函数。显然可以被滥用。具有类属性的class
也可以这种方式使用。