我有这样的文件结构:
project/
main_prog.py
tools/
script.py
md_script/
__init__.py
md_script.py
我在工具中搜索本地python模块。在这个例子中它是md_script。我想在我的代码中使用它作为安装的位置参数,但是当我使用它时,我遇到了错误:
./jsh.py md_script
usage: jsh.py [-h] {install,call,list,log,restore} ... [md_script]
jsh.py: error: invalid choice: 'md_script' (choose from 'install', 'call', 'list', 'log', 'restore')
ubuntu14.10上的python3.4 这是我的代码:
parser = argparse.ArgumentParser(prog='jsh.py',
description='Some help.', epilog='Example of usage: some help')
subparsers = parser.add_subparsers()
parser_install = subparsers.add_parser('install', help = 'Install new project.')
parser_install.add_argument('install', nargs='?', help = 'Name of project to be installed')
if os.path.isdir(full/path/to/tools/):
name_arg = next(os.walk(full/path/to/tools))[1]
tools_arg = parser.add_argument_group('Tools', 'Modules from tools')
for element in name_arg:
tools_arg.add_argument(element, nargs='?', help='md_script description')
args = parser.parse_args()
try:
if not len(sys.argv) > 1:
parser.print_help()
elif 'install' in args:
do_some_stuff
elif element in args:
do_some_md_script_stuff
else:
parser.print_help()
答案 0 :(得分:2)
<img id="Image-Maps-Com-image-maps-2015-08-31-103251" src="http://www.image-maps.com/m/private/58808/60863-ue1h8277se3mkfllaet1lledi0_worldmap.png" border="0" width="908" height="494" orgWidth="908" orgHeight="494" usemap="#image-maps-2015-08-31-103251" alt="" />
<map name="image-maps-2015-08-31-103251" id="ImageMapsCom-image-maps-2015-08-31-103251">
<area alt="North America" title="North America" href="http://www.google.com" shape="poly" coords="178,249,117,207,98,156,46,104,121,59,158,61,240,41,396,22" style="outline:none;" target="_blank" onclick="window.open("http://www.google.com");" onmouseover="if(document.images) document.getElementById('Image-Maps-Com-image-maps-2015-08-31-103251').src= 'http://i.imgur.com/B9N2Zbv.png';" onmouseout="if(document.images) document.getElementById('Image-Maps-Com-image-maps-2015-08-31-103251').src= 'http://www.image-maps.com/m/private/58808/60863-ue1h8277se3mkfllaet1lledi0_worldmap.png';" />
行显示错误:
usage
您需要使用类似
的内容usage: jsh.py [-h] {install,call,list,log,restore} ... [md_script]
您指定了子分析符,因此您必须为其指定一个子分析符。
从jsh.py install md_script
开始,您似乎还创建了其他未在代码中显示的子代理usage
,call
等。
您还可以在创建subparser后定义位置参数。这就是list
来自的地方。注意制作大量[md_script]
位置(包括nargs='?'
子解析器的参数)。这可能会让您的用户感到困惑。事实上,它似乎让你感到困惑。请记住,install
实际上是一个位置参数(需要1个字符串的参数)。
我建议在创建一个复杂的解析器之前尝试使用更简单的解析器。
因此,根据您的评论和示例,我看到您的目标是让用户为模块命名,因此您的脚本可以通过某种方式或其他方式调用它。对于那些填充这些名称的子分子是有道理的。
我想知道你为什么还要创建一个具有相同名称的可选位置参数:
subparser
这是因为你使用属性的存在作为调用这个subparser的证据吗?
module_pars = subparsers.add_parser(element, help = 'Modules from tools')
module_pars.add_argument(element, nargs='?', help=element+' description')
elif element in args:
do_some_md_script_stuff
文档还有其他一些想法。
处理子命令的一种特别有效的方法是结合使用add_subparsers()方法和对set_defaults()的调用,以便每个子分析器知道它应该执行哪个Python函数。
和
但是,如果需要检查调用的子分析程序的名称,则add_subparsers()调用的dest关键字参数将起作用:
这些避免了'?'的混乱位置参数,释放你使用subparser参数获取真实信息。
argparse
现在您可以查看:
subparsers = parser.add_subparsers(dest='module')
....
for element in name_arg:
# module_pars = 'parser_'+element # this does nothing
module_pars = subparsers.add_parser(element, help = 'Modules from tools')
module_pars.set_defaults(func = do_some_md_script_stuff)
# or module_pars.set_default(element='I am here')
module_pars.add_argument('real_argument')
或
if args.module='md_script':
do_some_md_script_stuff(args)
使用替代if hasattr(args, 'func'):
func(args)
,您的原始测试仍应有效:
set_defaults
答案 1 :(得分:0)
if os.path.isdir(TOOLS_PATH):
name_arg = next(os.walk(TOOLS_PATH))[1]
for element in name_arg:
module_pars = 'parser_'+element
module_pars = subparsers.add_parser(element, help = 'Modules from tools')
module_pars.add_argument(element, nargs='?', help=element+' description')
我没有测试它,因为我没有测试模块,但./jsh.py md_script
进入elif element in args: print('md_script')
并打印字符串。所以它看起来很有效。
感谢所有回复。
编辑:我测试了它。在add_argument中我必须改变nargs ='?' for nargs ='*'来捕获多个参数。 为了从命令行中捕获参数,我使用了这个:
elif args:
for element in name_arg:
if element in args:
element_arg = sys.argv[2:]
done_cmd,msg = opt_exec_module(element,*element_arg)
my_logger(done_cmd,msg)
不是很优雅,但它有效。