Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Argparse optional stdin argument

I am trying to specify an optional argument that takes stdin. This will be mainly used for piping data in my program, so someprog that outputs | python my_prog.

I followed the argparse documentation and I read a lot of questions/answers on this on Stackoverflow but none of them seem to work for me.

Here's what I originally have:

parser = argparse.ArgumentParser(description='Upgrade Instance.')
parser.add_argument('--app', '-a', dest='app', action='store', required=True)
parser.add_argument('--version', '-v', dest='version', action='store', default='', required=False)
parser.add_argument('--config', '-c', dest='config', action='store', default = '', required=False)
args = parser.parse_args()

Now what I want to do is allow the user to pass in version using a pipe, instead of passing it in.

I added parser.add_argument('infile', nargs='?', type=argparse.FileType('r'), default=sys.stdin) to the top but that makes it a positional argument. How is that possible? I thought nargs=? makes it optional.

I need it to be an optional argument. So I changed it to:

parser.add_argument('--infile', nargs='?', type=argparse.FileType('r'), default=sys.stdin)

This makes it an optional argument, but the program hangs waiting for stdin as thats default, if no pipe is passed. Removing the default=sys.stdin and piping something into my program I get:

close failed in file object destructor:
sys.excepthook is missing
lost sys.stderr

when running it. When I print args, I get: Namespace(app='app', config='', g=False, hosts='03.app', infile=None, version='').

It seems what I am doing is very simple, common and many people asked about it. But it doesn't seem to be working with me.

Any suggestions on how I can get it working?

like image 523
darksky Avatar asked Nov 13 '13 23:11

darksky


1 Answers

This does it... without specifying arguments. If you pass pipe input to the program it goes, it you don't, it still goes. raw_input() will work as well.

import sys

if not sys.stdin.isatty():
    stdin = sys.stdin.readlines()
    print stdin
    sys.stdin = open('/dev/tty')
else:
    print "No stdin"

test_raw = raw_input()
print test_raw

Demo -

rypeck$ echo "stdin input" | python test_argparse.py -a test 
['stdin input\n']
raw_input working!
raw_input working!
rypeck$ python test_argparse.py -a test
No stdin
raw_input working!
raw_input working!
like image 97
RyPeck Avatar answered Sep 29 '22 06:09

RyPeck