up vote 1 down vote favorite


I have a CLI script and want him to read data from a file. It should be able to read it in two ways :

  • cat data.txt | ./my_script.py
  • ./my_script.py data.txt

A bit like grep, for example.

What I know:

  • sys.argv and optparse let me read any args and options easily.
  • sys.stdin let me read data piped in
  • fileinput make the full process automatic


  • using fileinput use stdin and any args as input. So I can't use options that are not filenames as it tries to open them.
  • sys.stdin.readlines() work fine, but it I don't pipe any data, it hangs until I enter Ctrl + D
  • I don't know how to implement "if nothing in stdin, read from a file in args" because stdin is always True in a boolean context.

I'd like a portable way to do so is possible.


71% accept rate
Thanks all, I learned a lot today. – e-satis Feb 15 at 12:30

4 Answers

up vote 4 down vote accepted

Process your non-filename arguments however you'd like, so you wind up with an array of non-option arguments, then pass that array as the parameter to fileinput.input():

import fileinput
for line in fileinput.input(remaining_args):
I like that, it seems highly effective. Is there anything bad I'm missing? – e-satis Feb 15 at 10:40
I believe that this will provide behaviour similar to other Unix commands. In another comment you said you're slightly concerned about the hang-until-input effect when no arguments are given; unless you take steps to notice when no arguments are passed, this will still happen. There's no reason you shouldn't catch this case, though, as passing '-' as a parameter will still read from stdin. – Andrew Aylett Feb 15 at 11:00
I will use a combination of Ignocio's advice and Andrew's solution. – e-satis Feb 15 at 12:33

up vote 2 down vote

Argparse allows this to be done in a fairly easy manner, and you really should be using it instead of optparse unless you have compatibility issues.

The code would go something like this:

import argparse
= argparse.ArgumentParser()
.add_argument('--input', type = argparse.FileType('r'), default = '-')

Now you have a parser that will parse your command line arguments, use a file if it sees one, or use standard input if it doesn't.

Thanks to you as well. I'm learning a lot today! Anyway, don't you think there is a way to do that with the standard lib? If not, I'm ok with argparse. But optparse does exist... – e-satis Feb 15 at 10:41
argparse is pretty tiny, is pure python code and is also nicer to use than optparse. While I wouldn't normally want to add a new dependancy to a project just to read in the command line options, the three factors above have made argparse more than worthwhile in my experience. – mavnn Feb 15 at 10:56
This can be done in the same volume of code in optparse. – S.Lott Feb 15 at 11:24
@S.Lott I didn't know that, thanks for mentioning. In any case, I recommended argparse for its overall benefits anyway. – sykora Feb 15 at 14:49
up vote 2 down vote

There is no reliable way to detect if sys.stdin is connected to anything, nor is it appropriate do so (e.g., the user wants to paste the data in). Detect the presence of a filename as an argument, and use stdin if none is found.

Thanks to both of you. Since I lack of the necessary knowledge to choose between your answer and gnibbler's, what are the drawbacks of each ? Them seem both valid. – e-satis Feb 15 at 10:05
Oh, just tried this approach but their is a problem: if there is no files and no stdin, I end up reading stdin and it hangs. How can I write an error message to the user to tell him to provide data? – e-satis Feb 15 at 10:07
Note well that the hang-until-EOF is inevitable here if someone runs it without a filename -- this is standard behavior in the Unix world. see also grep, cat, etc.. If this isn't acceptable, the only portable way you can avoid it is to use another typical convention wherein providing a filename of '-' means 'read from stdin' (or write to stdout). – Nicholas Knight Feb 15 at 10:08
Actually, I just fired grep without any input. I just fired grep and sed without any input and they don't hang. – e-satis Feb 15 at 10:25
Ok you are right. Cat does wait for input But how does grep and sed do? I give them no args, I guess they check, they see no arg, then they look for stdin, why do they manage to display the message ? – e-satis Feb 15 at 10:28
show 3 more comments
up vote 2 down vote

For unix/linux you can detect whether data is being piped in by looking at os.isatty(0)

$ date | python -c "import os;print os.isatty(0)"
$ python
-c "import os;print os.isatty(0)"

I'm not sure there is an equivalent for Windows.

edit Ok, I tried it with python2.6 on windows XP

C:\Python26>echo "hello" | python.exe -c "import os;print os.isatty(0)"  

:\Python26> python.exe -c "import os;print os.isatty(0)"  

So maybe it it not all hopeless for windows

Thanks to both of you. Since I lack of the necessary knowledge to choose between your answer and Ignocio's, what are the drawbacks of each ? Them seem both valid. – e-satis Feb 15 at 10:04
@e-satis: What happens if no filename is passed as an argument? When you can answer this question you'll know what you need to do. – Ignacio Vazquez-Abrams Feb 15 at 10:06
For now, this seems to work so I accept it. Thanks again. I'm still interested in knowing the issues with what I'm doind. What is a tty, and why does this work? When will it not? – e-satis Feb 15 at 10:10
Note that this is defined as Unix-only in the docs, so you hurt portability to Windows and possibly other operating systems. It also assumes you'll never want to just paste data in, which is a silly assumption. – Nicholas Knight Feb 15 at 10:12
@e-satis: A tty technically stands for teletype terminal. These days it really just means it's an interactive terminal. The particular concept used by isatty() is non-portable outside Unix, however. – Nicholas Knight Feb 15 at 10:15
show 6 more comments
当前网页内容, 由 大妈 ZoomQuiet 使用工具: ScrapBook :: Firefox Extension 人工从互联网中收集并分享;
若有不妥, 欢迎评注提醒:


订阅 substack 体验古早写作:

点击注册~> 获得 100$ 体验券: DigitalOcean Referral Badge

关注公众号, 持续获得相关各种嗯哼:


关于 ~ DebugUself with DAMA ;-)
公安备案号: 44049002000656 ...::