有什么方法可以指示argparse(Python 2.7)从sys.argv中删除找到的参数?

hBy*_*2Py 1 python python-2.7 argparse

在开发过程中,我正处于过渡阶段,即将变成一个相当庞大的Python 2.7项目。现在,我将所有unittest班级集中在各自的模块中tests.py,该模块大约有3300行。这太疯狂了,无法导航,到处都是坏习惯,等等。

因此,我当前的任务是将其重构为子模块。作为此重构的一部分,我想简化从命令行运行一部分测试的过程。例如:

$ python tests.py --all                         <--- runs *all* tests
$ python tests.py --utils_base                  <--- runs all tests on .utils
$ python tests.py --utils_vector                <--- runs all tests on .utils.vector
$ python tests.py --utils_base --utils_vector   <--- runs all tests on .utils.vector & .utils
Run Code Online (Sandbox Code Playgroud)

因此,我开始使用进行设置argparse。我进行了基本ArgumentParser设置,没有问题,并且帮助消息显示正常:

$ python tests.py -h
usage: tests.py [-h] [--all] [--utils_base]

optional arguments:
  -h, --help    show this help message and exit

Global Options:
  --all         Run all tests (overrides any other selections)

opan.base.utils Tests:
  --utils_base  Run all .utils tests
Run Code Online (Sandbox Code Playgroud)

但是,当我去运行一些测试时,它崩溃并显示“参数无法识别”错误:

$ python tests.py --all
option --all not recognized
Usage: tests.py [options] [test] [...]

Options:
  -h, --help       Show this message
  -v, --verbose    Verbose output
  -q, --quiet      Minimal output
  -f, --failfast   Stop on first failure
  -c, --catch      Catch control-C and display results
  -b, --buffer     Buffer stdout and stderr during test runs

Examples:
  tests.py                               - run default set of tests
  tests.py MyTestSuite                   - run suite 'MyTestSuite'
  tests.py MyTestCase.testSomething      - run MyTestCase.testSomething
  tests.py MyTestCase                    - run all 'test*' test methods
                                               in MyTestCase
Run Code Online (Sandbox Code Playgroud)

经过一些调试之后,我终于意识到要解析的命令行参数将tests.py保留在其中sys.argv并传递给unittest.main。(回想起来,Examples:对错误消息部分的仔细阅读应该早就让我明白了。)

因此,为解决此问题,我在下面添加了标记的代码,以sys.argv在将控件传递给之前清除自定义参数unittest.main

# Arguments for selecting test suites
ALL = 'all'
UTILS_BASE = 'utils_base'

# Collecting the args together for iteration later
test_args = [ALL, UTILS_BASE]

...

# Strip from sys.argv any test arguments that are present
for a in test_args:                 <---  
    str_arg = '--{0}'.format(a)     <--- ADDING THESE MAKES UNITTEST HAPPY
    if str_arg in sys.argv:         <---
        sys.argv.remove(str_arg)    <---
Run Code Online (Sandbox Code Playgroud)

有没有办法告诉argparse.remove参数从发现sys.argv,也许在施工了ArgumentParser?我已经搜索了argparse文档页面,但是我一生都找不到能做到这一点的选项。

cne*_*son 5

您想要parse_known_args()

from __future__ import print_function
import argparse
import sys

def main():
    print(sys.argv)


if __name__ == "__main__":
    parser = argparse.ArgumentParser()

    parser.add_argument('--all', action='store_true')
    parser.add_argument('--utils_base', action='store_true')

    args, left = parser.parse_known_args()

    sys.argv = sys.argv[:1]+left

    main()
Run Code Online (Sandbox Code Playgroud)

虽然,我必须问。您为什么要编写自己的测试跑步者?unittest模块允许您从cli运行特定的测试集:

# run test from a spefiic class
$ python -m unittest module.tests.group.TestSpecific
# all possible options
$ python -m unittest --help
Usage: python -m unittest [options] [tests]

Options:
  -h, --help       Show this message
  -v, --verbose    Verbose output
  -q, --quiet      Minimal output
  -f, --failfast   Stop on first failure
  -c, --catch      Catch control-C and display results
  -b, --buffer     Buffer stdout and stderr during test runs

Examples:
  python -m unittest test_module               - run tests from test_module
  python -m unittest module.TestClass          - run tests from module.TestClass
  python -m unittest module.Class.test_method  - run specified test method

[tests] can be a list of any number of test modules, classes and test
methods.

Alternative Usage: python -m unittest discover [options]

Options:
  -v, --verbose    Verbose output
  -f, --failfast   Stop on first failure
  -c, --catch      Catch control-C and display results
  -b, --buffer     Buffer stdout and stderr during test runs
  -s directory     Directory to start discovery ('.' default)
  -p pattern       Pattern to match test files ('test*.py' default)
  -t directory     Top level directory of project (default to
                   start directory)

For test discovery all test modules must be importable from the top
level directory of the project.
Run Code Online (Sandbox Code Playgroud)

如果您在分组和运行测试方面需要更大的灵活性,建议您选择鼻子测试