Skip to main content
 首页 » 编程设计

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

2025年05月04日27shanyou

我完全处于开发过程的中游,正在转变为一个相当重要的 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 

因此,我开始使用 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 

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

$ 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 

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

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

# 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)    <--- 

有没有办法告诉 argparse .remove 它从 sys.argv 中找到的参数,也许是在 的构造中>ArgumentParser?我已经搜索了 argparse 文档页面,但我终究找不到可以做到这一点的选项。

请您参考如下方法:

你想要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() 

虽然,我必须问。你为什么要编写自己的测试运行程序? 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. 

如果您在分组和运行测试方面需要更大的灵 active ,我建议您查看 nosetest