如何在Python中从stdin或文件读取(如果没有数据管道)?
我有一个命令行脚本,想让它从一个文件中读取数据。它应该能通过两种方式来读取数据:
cat data.txt | ./my_script.py
./my_script.py data.txt
这有点像grep
的用法。
我知道的事情:
sys.argv
和optparse
可以让我轻松读取任何参数和选项。sys.stdin
可以让我读取通过管道传入的数据。fileinput
可以让整个过程自动化。
不幸的是:
- 使用
fileinput
时,它会把标准输入和任何参数都当作输入。所以我不能使用那些不是文件名的选项,因为它会尝试打开它们。 sys.stdin.readlines()
工作得很好,但如果我不输入任何数据,它会一直卡在那里,直到我按下Ctrl + D。- 我不知道怎么实现“如果标准输入没有数据,就从参数中的文件读取”,因为在布尔上下文中,
stdin
总是被认为是True
。
如果可能的话,我希望有一个便携的方式来实现这个功能。
6 个回答
9
在Unix/Linux系统中,你可以通过查看 os.isatty(0)
来判断是否有数据被传入。
$ date | python -c "import os;print os.isatty(0)"
False
$ python -c "import os;print os.isatty(0)"
True
我不太确定在Windows上有没有类似的功能。
补充 好吧,我在Windows XP上用python2.6试了一下。
C:\Python26>echo "hello" | python.exe -c "import os;print os.isatty(0)"
False
C:\Python26> python.exe -c "import os;print os.isatty(0)"
True
所以也许在Windows上并不是完全没有希望。
20
Argparse 这个工具可以很简单地处理命令行参数,除非你有兼容性的问题,否则你真的应该用它,而不是 optparse
。
代码大概是这样的:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--input', type = argparse.FileType('r'), default = '-')
现在你有了一个解析器,它会解析你的命令行参数。如果它发现有文件,就会使用这个文件;如果没有文件,它就会使用标准输入。
12
你可以随意处理那些不是文件名的参数,这样你就能得到一个非选项参数的数组。然后把这个数组作为参数传给 fileinput.input()
:
import fileinput
for line in fileinput.input(remaining_args):
process(line)