Reputation: 4946
I'm using Click for command line argument parsing, and I'd like to use Python's fileinput library in one sub-command, but it seems Click leaves sys.argv
as it is:
test.py:
import fileinput
import click
@click.group()
@click.option('-x', is_flag=True)
def cli(x):
pass
@cli.command()
@click.option('-y', is_flag=True)
def read(y):
for f in fileinput.input():
for line in f:
print(line)
if __name__ == '__main__':
cli()
Test:
% python3 test.py -x read -y
Traceback (most recent call last):
File "test.py", line 17, in <module>
cli()
File "/usr/lib/python3.8/site-packages/click/core.py", line 829, in __call__
return self.main(*args, **kwargs)
File "/usr/lib/python3.8/site-packages/click/core.py", line 782, in main
rv = self.invoke(ctx)
File "/usr/lib/python3.8/site-packages/click/core.py", line 1259, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/usr/lib/python3.8/site-packages/click/core.py", line 1066, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/usr/lib/python3.8/site-packages/click/core.py", line 610, in invoke
return callback(*args, **kwargs)
File "test.py", line 12, in read
for f in fileinput.input():
File "/usr/lib/python3.8/fileinput.py", line 248, in __next__
line = self._readline()
File "/usr/lib/python3.8/fileinput.py", line 366, in _readline
self._file = open(self._filename, self._mode)
FileNotFoundError: [Errno 2] No such file or directory: '-x'
Now of course I'd need to add some Click decorator to allow for arbitrary number of trailing arguments, but even the simple case for when there are no remaining arguments and fileinput takes sys.stdin
, doesn't work.
AFAIK Python's argparse properly augments sys.argv
so it'd work without problems. Can Click do that as well? How?
Note that I realize that it's probably possible to do what fileinput does with Click's decorators, and I can and will read about it in documentation. What I didn't find in the documentation and what I'm asking here is how to make Click pop arguments out of sys.argv
like argparse does.
Upvotes: 3
Views: 495
Reputation: 40763
I'm late answering this question, but better late than never. Woky is correct when suggesting adding arbitrary arguments.
import fileinput
import click
@click.group()
@click.option('-x', is_flag=True)
def cli(x):
pass
@cli.command()
@click.argument("file", nargs=-1)
@click.option('-y', is_flag=True)
def read(file, y):
for line in fileinput.input(file):
print(line, end='')
if __name__ == '__main__':
cli()
Notes
file == ()
file == ()
, fileinput.input()
knows to take input from stdin
. This is different from file is None
, in which case, fileinput.input()
will take arguments from sys.argv
for
loopline
contains the ending new line, I call print()
with end='')
Upvotes: 0