调试时模拟 argparse 命令行参数输入

Posted

技术标签:

【中文标题】调试时模拟 argparse 命令行参数输入【英文标题】:Simulating argparse command line arguments input while debugging 【发布时间】:2018-11-25 22:36:50 【问题描述】:

此线程是上一个线程的扩展,可以在here 找到。 说,我有一个代码有两个目的,1)从整数列表中打印一个最大数; 2)创建一个新目录。

import argparse
import os

parser = argparse.ArgumentParser()
parser.add_argument('integers', metavar='N', type=int, nargs='+',
                    help='an integer for the accumulator')

parser.add_argument('--sum', dest='accumulate', action='store_const',
                    const=sum, default=sum,
                    help='sum the integers (default: find the max)')

parser.add_argument("--output_dir", type=str, default="data/xx")

def main(args):
    os.makedirs(args.output_dir)
    print args.accumulate(args.integers)

if __name__=='__main__':
    args = parser.parse_args()  # Disable during debugging @ Run through terminal
    # args = argparse.Namespace(integers = 1, output_dir= 'mydata_223ss32')  # Disable when run through terminal: For debugging process
    main(args)

这些语句可以通过终端执行

python test_file.py --output_dir data/xxxx 2 2 5 --sum

但是,对于调试过程,我想跳过终端的使用。可以从here 中找到hpaulj 的想法只是修改了

if __name__=='__main__': 

进入

if __name__=='__main__':
    args = argparse.Namespace(output_dir= 'mydata')  # Disable when run through terminal: For debugging process
    main(args)

但是,我还想在调试过程中包含一个整数列表。包括整数列表和目录地址如下输出错误

args = argparse.Namespace(integers = "2 2 5", output_dir= 'mydata') 

请问我哪里做错了。

提前致谢

【问题讨论】:

如果你想调试 argparse 的 解析,我建议更改 sys.argv.parse_args() 之前),而不是跳过解析步骤。 嗨@jedwards。我可以知道如何更改 sys.argv。谢谢 如果您致力于使用命名空间对象,您可能需要Namespace(..., integers=[1, 2, 3], ...) 嗨@jedwards,执行你的建议给我一个错误> AttributeError: 'Namespace' object has no attribute 'accumulate' sys.argv 只是一个列表,其中第一项是脚本的名称,其余的是您在调用时传递给脚本的参数。所以./script.py --output_dir foo 1 2 3 将导致sys.argv 成为['script.py', '--output_dir', 'foo', '1', '2', '3']——并且您可以在调用parser.parse_args() 之前随意编辑该列表。 【参考方案1】:

通过将代码稍微更改为:

import argparse
import sys

parser = argparse.ArgumentParser()
parser.add_argument('integers', metavar='N', type=int, nargs='+',
                    help='an integer for the accumulator')

parser.add_argument('--sum', dest='accumulate', action='store_const',
                    const=sum, default=sum,
                    help='sum the integers (default: find the max)')

parser.add_argument("--output_dir", type=str, default="data/xx")

def main(args):
    #os.makedirs(args.output_dir)              # XXX: Commented out for debugging
    print(args.accumulate(args.integers))

if __name__=='__main__':
    print(sys.argv)
    args = parser.parse_args()  # Disable during debugging @ Run through terminal
    # args = argparse.Namespace(integers = 1, output_dir= 'mydata_223ss32')  # Disable when run through terminal: For debugging process
    print(args)
    main(args)

我们可以看到,如果我们调用脚本:./test3.py --output_dir foo 1 2 3

我们的输出是:

['test3.py', '--output_dir', 'foo', '1', '2', '3'] 命名空间(accumulate=, integers=[1, 2, 3], output_dir='foo') 6

所以,如果你想模拟命令行参数,你有两个选择:

1) 编辑sys.argv(个人首选):

if __name__=='__main__':
    # Override sys.argv
    sys.argv = ['test3.py', '--output_dir', 'foo', '1', '2', '3']
    args = parser.parse_args()
    main(args)

2) 创建Namespace 对象:

if __name__=='__main__':    
    #args = parser.parse_args()  # Disable during debugging @ Run through terminal
    args = argparse.Namespace(accumulate=sum, integers=[1,2,3], output_dir='foo')
    main(args)

第二种方法的问题是双重的。首先,您通过执行此操作跳过了调试过程中非常重要的部分,调试 argparse 配置并确保按预期解析参数。其次,您的 argparse 配置添加的隐式默认值必须在此处定义(例如,您的 --sum 参数/accumulate)。如果您采用第一种方法,argparse 将处理 sys.argv 并添加累积,而无需您进行任何更改。在第二种方法中,我们必须添加accumulate=sum 才能使其按预期运行。

【讨论】:

感谢详细的解释和一个很好的例子。真的很感激。由于声誉数量较少,我无法提高此回复的评分。【参考方案2】:

要向 [jedwards Answer][1] 添加更多信息:

我使用 pycharm 来达到同样的效果,我需要稍微改变 jedwards 的命题,这样sys.argv 不会被覆盖而是被修改。应该留下列表sys.argv[0] 的第一个条目,因为它包含正在运行的文件的路径。如果不这样做,变量 parser.prog 会被弄乱,因此无法正常工作。

您无需像 jedwards 那样手动添加文件名作为第一个列表条目,您只需附加到 sys.argv 并扩展列表:

if __name__=='__main__':
    # Append additional arguments to sys.argv
    sys.argv = sys.argv + ['--output_dir', 'foo', '1', '2', '3']
    args = parser.parse_args()
    main(args)

这使它能够适应文件名的更改。 [1]:https://***.com/a/50886791/7705525

【讨论】:

以上是关于调试时模拟 argparse 命令行参数输入的主要内容,如果未能解决你的问题,请参考以下文章

Python3中使用argparse模块解析命令行参数

Python3中使用argparse模块解析命令行参数

Python中最好用的命令行解析工具:argparse

Python命令行参数处理之argparse模块

Python Argparse Moudle

Argparse 命令行解析模块常用参数