我有这行代码,可以捕获传递给我的Python脚本的所有文件名:
@click.argument("logs", nargs=-1, type=click.File('r'), required=1)
当没有传递文件名时,我想默认为-
,即标准输入。所以,如果我尝试:
@click.argument("logs", nargs=-1, type=click.File('r'), required=1, default="-")
点击变得不满意并引发此错误:
TypeError:不支持将nargs = -1与默认值结合使用。
是否有解决方法?我尝试设置nargs=0
,但这会引发另一个错误:
IndexError:元组索引超出范围
答案 0 :(得分:2)
要默认将stdin
用于可能为空的文件列表,可以定义一个自定义参数类,例如:
class FilesDefaultToStdin(click.Argument):
def __init__(self, *args, **kwargs):
kwargs['nargs'] = -1
kwargs['type'] = click.File('r')
super().__init__(*args, **kwargs)
def full_process_value(self, ctx, value):
return super().process_value(ctx, value or ('-', ))
将此行为定义为类可提供方便的重用。
@click.command()
@click.argument("logs", cls=FilesDefaultToStdin)
def main(logs):
...
之所以可行,是因为click是一个设计良好的OO框架。 @click.argument()
装饰器通常会实例化click.Argument
对象,但允许使用cls
参数来覆盖此行为。因此,在我们自己的类中从click.Argument
继承并重写所需的方法是相对容易的事情。
在这种情况下,我们将覆盖click.Argument.full_process_value()
。在我们的full_process_value()
中,查找一个空的参数列表,如果为空,则将-
(stdin)参数添加到列表中。
此外,我们自动分配nargs=-1
和type=click.File('r')
参数。
答案 1 :(得分:1)
由于click
明确表示他们禁用了问题所需的特定功能(如this issue在其项目中的报道),因此需要一种解决方法,并且可以轻松地将其实施为Python函数(而不是其他答案的注释所建议的,更多的是bash代码)。
解决方法是简单地删除必需的参数并使用一条语句处理丢失的日志(类似于this commit所做的引用链接问题的操作):
import sys
import click
@click.command()
@click.argument("logs", nargs=-1, type=click.File('r'))
def main(logs):
if not logs:
logs = (sys.stdin,)
print(logs)
# do stuff with logs
if __name__ == '__main__':
main()
执行示例
$ python fail.py
(<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>,)
$ python fail.py -
(<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>,)
$ python fail.py foo bar
(<_io.TextIOWrapper name='foo' mode='r' encoding='UTF-8'>, <_io.TextIOWrapper name='bar' mode='r' encoding='UTF-8'>)
答案 2 :(得分:0)
以下代码:
import click
@click.command()
@click.option('--logs', '-l', multiple=True, default='-')
def cli(logs):
click.echo('\n'.join(logs))
将产生以下内容:
$ myhello -l foo.log -l bar.log -l baz.log
foo.log
bar.log
baz.log
$ myhello
-
因此,如果您只是可以使用重复的参数以不同的方式调用程序,那将是您所需要的解决方法。