我有
client.py
模块,它使用 argparse
用于 CLI:
class Client:
#some logic
...
def main(arguments=None):
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("n", nargs='?', type=int, default=10, help="number of threads")
parser.add_argument("f", nargs='?', default="urls.txt", help="file with URLs")
args = parser.parse_args(arguments)
#some logic unrelated to argparse
...
if __name__ == "__main__":
main()
还有
tests.py
模块进行测试:
import sys
from unittest.mock import patch
import client
def test(self):
with patch.object(sys, 'argv', ['n', 10, 'f', "urls.txt"]):
client.main()
client.py
模块在 CLI 和脚本中运行良好。但是当它调用 pytest 测试时 - 出现错误:
def test(self):
with patch.object(sys, 'argv', ['n', 10, 'f', "urls.txt"]):
> client.main()
test_client_server.py:60:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
client.py:55: in main
args = parser.parse_args(arguments)
..\..\..\AppData\Local\Programs\Python\Python311\Lib\argparse.py:1862: in parse_args
args, argv = self.parse_known_args(args, namespace)
..\..\..\AppData\Local\Programs\Python\Python311\Lib\argparse.py:1895: in parse_known_args
namespace, args = self._parse_known_args(args, namespace)
..\..\..\AppData\Local\Programs\Python\Python311\Lib\argparse.py:1938: in _parse_known_args
option_tuple = self._parse_optional(arg_string)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = ArgumentParser(prog='n', usage=None, description=None, formatter_class=<class 'argparse.ArgumentDefaultsHelpFormatter'>, conflict_handler='error', add_help=True)
arg_string = 10
def _parse_optional(self, arg_string):
# if it's an empty string, it was meant to be a positional
if not arg_string:
return None
# if it doesn't start with a prefix, it was meant to be positional
> if not arg_string[0] in self.prefix_chars:
E TypeError: 'int' object is not subscriptable
..\..\..\AppData\Local\Programs\Python\Python311\Lib\argparse.py:2228: TypeError
我尝试过模拟
sys.argv
- 它可以很好地模拟 ['n', 10, 'f', 'urls.txt']
,但测试还是失败并出现错误。arg_string = 10
会出错?没看懂。
你的解析器,没有所有的 pytest 包袱(在
ipython
会话中):
In [10]: def main(arguments=None):
...: parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
...: parser.add_argument("n", nargs='?', type=int, default=10, help="number of threads")
...: parser.add_argument("f", nargs='?', default="urls.txt", help="file with URLs")
...: args = parser.parse_args(arguments)
...: return args
帮助:
In [11]: main(['-h'])
usage: ipykernel_launcher.py [-h] [n] [f]
positional arguments:
n number of threads (default: 10)
f file with URLs (default: urls.txt)
options:
-h, --help show this help message and exit
有效的 argv 列表 - 两个字符串,用于两个位置参数:
In [12]: main(['10','text.file'])
Out[12]: Namespace(n=10, f='text.file')
尝试你的
argv
,但使用“10”字符串:
In [13]: main(['n', '10', 'f', "urls.txt"])
usage: ipykernel_launcher.py [-h] [n] [f]
ipykernel_launcher.py: error: argument n: invalid int value: 'n'
它试图将 'n' 字符串解析为
int
。您定义了位置,而不是标记的参数,因此 'n' 和 'f' 字符串不属于。
您的错误 - 使用数字
10
而不是字符串:
In [14]: main(['n', 10, 'f', "urls.txt"])
TypeError: 'int' object is not subscriptable