有什么方法可以指示 argparse (Python 2.7) 从 sys.argv 中删除找到的参数?
Is there any way to instruct argparse (Python 2.7) to remove found arguments from sys.argv?
我完全处于开发过程的中游,正在转变为相当重要的 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
然而,当我去 运行 一些测试时,它崩溃了 'argument not recognized' 错误:
$ 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
文档页面,但终究找不到合适的选项。
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()
虽然,我必须问。你为什么要编写自己的测试 运行ner? 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.
如果您需要更灵活的分组和 运行ning 测试,我建议您查看 nosetest
我完全处于开发过程的中游,正在转变为相当重要的 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
然而,当我去 运行 一些测试时,它崩溃了 'argument not recognized' 错误:
$ 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
文档页面,但终究找不到合适的选项。
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()
虽然,我必须问。你为什么要编写自己的测试 运行ner? 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.
如果您需要更灵活的分组和 运行ning 测试,我建议您查看 nosetest