全局变量如何处理导入的函数?

时间:2017-01-30 23:35:59

标签: python global argparse

我有多个需要由主脚本包装的脚本。每个脚本都包含在该脚本中使用的包含输入参数的函数。

例如,foo.py:

import argparse
import sys
import os 

parser = argparse.ArgumentParser()
parser.add_argument("foo_input_dir")
parser.add_argument("foo_ouput_dir")
args = parser.parse_args()

def foo(input_file):
    print input_file
    print args.foo_input_dir
    print args.foo_ouput_dir

并且主脚本应该输入带有文件和文件列表的目录,bar.py:

import argparse
import foo

parser = argparse.ArgumentParser()
parser.add_argument("main_input")
parser.add_argument("input_dir")
parser.add_argument("ouptut_dir")
args = parser.parse_args()

def bar():  
    print args
    foo.foo(main_input)

bar()

但是,当我尝试在命令行中运行它时,出现以下错误:

使用3个参数,bar.py

需要
  

python bar.py示例/ usr / / bin /

     
    

用法:bar.py [-h] foo_input_dir foo_ouput_dir

         

bar.py:错误:无法识别的参数:/ bin /

  

有2个参数,

  

python bar.py / usr / / bin /

     
    

用法:bar.py [-h] main_input input_dir ouptut_dir

         

bar.py:错误:参数太少

  

我正在尝试foo()使用bar.py作为args.foo_input_dirargs.foo_output_dir的输入。

我该如何处理这个问题?

1 个答案:

答案 0 :(得分:0)

这不是全局变量的问题。发生的事情是两个解析器都在命令行sys.argv上运行。

当您运行bar.py时,它会导入foo。作为导入的一部分,它创建解析器并执行parse_args,期望2个字符串。如果它变为3,则会引发错误并退出。

但是现在main创建了自己的解析器并运行它。如果它只看到foo接受的2,它需要3个字符串和对象。

关键是两个解析器都使用相同的sys.argv

两个错误中的usage行清楚地表明哪个解析器正在反对。

通常,在同一代码中运行两个独立的解析器并不是一个好主意。你可以使它工作,但它需要更多的协调而不是它的价值。当人们尝试将自己的参数添加到由Google youtube API等导入包定义的API时,有几个SO问题。

通常我们将解析器放在if __name__块(或至少它的parser.parse_args调用)中的可导入模块中。这样它只在用作脚本时使用。导入时不使用它。

这两个文件一起工作

foo.py:

import argparse

def make_parser():
   parser = argparse.ArgumentParser()
   parser.add_argument("foo_input_dir")
   parser.add_argument("foo_ouput_dir")
   return parser

def foo(input_file):
    print input_file
    print 'foo', args

if __name__ == '__main__':
    parser = make_parser()
    args = parser.parse_args()
    foo('test')

bar.py

import argparse
import foo

def bar():
    print 'bar', args
    foo.foo(args.main_input)

parser = argparse.ArgumentParser()
parser.add_argument("main_input")
parser.add_argument("input_dir")
parser.add_argument("ouptut_dir")

if __name__ == '__main__':
    args = parser.parse_args()
    foo.args = args  # make args visible to foo.foo
    bar()

1827:~/mypy/stack41947308$ python foo.py a b
test
foo Namespace(foo_input_dir='a', foo_ouput_dir='b')
1828:~/mypy/stack41947308$ python bar.py a b c
bar Namespace(input_dir='b', main_input='a', ouptut_dir='c')
a
foo Namespace(input_dir='b', main_input='a', ouptut_dir='c')

bar.args中显示foo变量需要特殊步骤。  属性名称不同。

作为一般规则,在可能导入的函数中使用全局变量不是一个好主意。可以使用保证在其自己的模块中定义的全局变量(模块常量),但不要依赖于将由导入器设置的全局变量。将所有变量作为参数传递更安全。