我正在尝试使用argparse创建带参数的脚本,但我无法使用。
我的脚本名称为pipeline
,它有一些选项参数,如-b,-c,-i和-r。
如果你调用脚本./pipeline -b
应该提出错误,要求提供git存储库路径,但我无法做到这一点。
from git import Repo
import os
import sys
import subprocess
import argparse
class Ci:
def build(self,args):
cloned_repo = Repo.clone_from(args)
print("clonning repository " + args)
cloned_repo
dir = git.split('/')(-1)
if os.path.isdir(dir):
print("repository cloned successfully")
else:
print("error to clone repository")
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-b','-build',action='store_true', help='execute mvn clean install')
parser.add_argument('-c','-compress',action='store_true',help='zip a directory recursively')
parser.add_argument('-i','-integration',action='store_true',help='execute mvn verify')
parser.add_argument('-r','-release',action='store_true',help='execute build,integration and compress respectively')
args = parser.parse_args()
if args.b:
a = Ci()
a.build()
if len(sys.argv) < 2:
parser.print_help()
sys.exit(1)
我无法使这个子参数工作,我找不到将此参数传递给build
函数的方法。
e.g:
./pipeline -b
Output: error missins git path
./pipeline -b https://git/repo
Output: clonning repo
并且字符串"https://git/repo"
必须作为参数传递给我的build
函数:
我怎样才能让它发挥作用?
答案 0 :(得分:3)
首先关于约定的注释:通常较长的选项名称前面有两个连字符,如'--build'
第二,'store_true'
是您使用'-b'
执行的操作,这意味着argparse并不期望在其后面有一个参数,它只是将args.build
变量设置为True
(和如果参数不存在,则会将其设置为False
)
尝试删除action='store_true'
,然后默认将它在参数列表中找到的下一个值存储到args.build
答案 1 :(得分:1)
我同意@hpaulj(为什么不接受答案?)。我猜您发现了问题所在,即store_true不接受参数,然后遵循hpaulj指示。
此外,由于标题的问题,我打开了这个问题,我期望下面的内容有所不同。我想找到一种方法将argparse参数传递给函数,并可能使用函数参数对其进行修改。这是我写的解决方案,以防其他人寻找它。可能需要调整它以解决位置参数,我还强调了使用vars(args)从argparse参数中获取字典以将dict-to-dict与args_dict比较的可能性:
def get_options(args_dict: dict):
""" get options from command-line,
update with function args_dict if needed """
args = get_cmd() # this is the function taking cmd-line arguments
for key, val in args_dict.items():
if not hasattr(args, key):
raise AttributeError('unrecognized option: ', key)
else:
setattr(args, key, val)
return(args)
答案 2 :(得分:0)
将代码缩减为:
import argparse
class Ci:
def build(self,args):
print("clonning repository " + args)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-b','-build',action='store_true', help='execute mvn clean install')
parser.add_argument('-c','-compress',action='store_true',help='zip a directory recursively')
parser.add_argument('-i','-integration',action='store_true',help='execute mvn verify')
parser.add_argument('-r','-release',action='store_true',help='execute build,integration and compress respectively')
args = parser.parse_args()
print(args)
if args.b:
a = Ci()
a.build()
我明白了:
1313:~/mypy$ python3 stack49408644.py -b
Namespace(b=True, c=False, i=False, r=False)
Traceback (most recent call last):
File "stack49408644.py", line 22, in <module>
a.build()
TypeError: build() missing 1 required positional argument: 'args'
解析器运行正常,看到args.b
到True
。但是对build
的调用是错误的。它与方法的定义不匹配。
提供“目录”也无济于事,因为-b
是True/False
1313:~/mypy$ python3 stack49408644.py -b foo
usage: stack49408644.py [-h] [-b] [-c] [-i] [-r]
stack49408644.py: error: unrecognized arguments: foo
您需要更改-b
以获取值,或者添加另一个带值的参数。
@AntiMatterDynamite展示了如何更改-b
。相反,我们添加:
parser.add_argument('adir', help='a directory for build')
并更改build
电话
a.build(args.adir)
现在将值传递给方法:
1322:~/mypy$ python3 stack49408644.py -b
usage: stack49408644.py [-h] [-b] [-c] [-i] [-r] adir
stack49408644.py: error: the following arguments are required: adir
1322:~/mypy$ python3 stack49408644.py -b foo
Namespace(adir='foo', b=True, c=False, i=False, r=False)
clonning repository foo
而是重新定义-b
:
parser.add_argument('-b','-build', help='execute mvn clean install')
if args.b is not None:
a = Ci()
a.build(args.b)
测试运行:
1322:~/mypy$ python3 stack49408644.py -b
usage: stack49408644.py [-h] [-b B] [-c] [-i] [-r]
stack49408644.py: error: argument -b/-build: expected one argument
1324:~/mypy$ python3 stack49408644.py -b foo
Namespace(b='foo', c=False, i=False, r=False)
clonning repository foo
所以你的解析器需要接受一个值。您需要将该值传递给您的代码。您似乎已经阅读了足够多的argparse
文档来获取print_help
和store_true
之类的内容,但错过了store
(默认)或位置的简单使用。你想做更复杂的事吗?