我有一个CLI脚本,希望它从文件中读取数据。它应该能够以两种方式阅读:
cat data.txt | ./my_script.py
./my_script.py data.txt
- 有点像grep
,例如。
我所知道的:
sys.argv
和optparse
让我轻松阅读任何参数和选项。sys.stdin
让我阅读fileinput
自动完成整个过程不幸的是:
fileinput
使用stdin和任何args作为输入。所以我不能使用非文件名的选项,因为它试图打开它们。sys.stdin.readlines()
工作正常,但如果我不管道任何数据,它会挂起,直到我输入 Ctrl + D stdin
在布尔上下文中始终是True
。如果可能的话,我想要一种可移植的方式来做到这一点。
答案 0 :(得分:20)
Argparse允许以相当简单的方式完成此操作,除非您遇到兼容性问题,否则您应该使用它而不是optparse
。
代码会是这样的:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--input', type = argparse.FileType('r'), default = '-')
现在你有一个解析你的命令行参数的解析器,如果它看到一个文件就使用它,或者如果没有则使用标准输入。
答案 1 :(得分:10)
按照你想要的方式处理你的非文件名参数,所以最后得到一个非选项参数数组,然后将该数组作为参数传递给fileinput.input():
import fileinput
for line in fileinput.input(remaining_args):
process(line)
答案 2 :(得分: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来说并非毫无希望。
答案 3 :(得分:4)
我是菜鸟,所以这可能不是一个好的答案,但我正在尝试做同样的事情(在命令行上允许一个或多个文件,否则默认为STDIN)。
我把最后的组合放在一起:
parser = argparse.ArgumentParser()
parser.add_argument("infiles", nargs="*")
args = parser.parse_args()
for line in fileinput.input(args.infiles):
process(line)
这似乎是在一个优雅的包中获得所有所需行为的唯一方法,而不需要命名args。就像使用unix命令一样:
cat file1 file2
wc -l < file1
不
cat --file file1 --file file2
希望得到资深惯用Pythonistas的反馈/确认,以确保我得到最好的答案。没有看到其他任何地方提到的完整解决方案,只是片段。
答案 4 :(得分:3)
没有可靠的方法来检测sys.stdin
是否与任何东西相关联,也不适合这样做(例如,用户想要粘贴数据)。检测文件名的存在作为参数,如果没有找到则使用stdin。
答案 5 :(得分:2)
您可以使用此功能来检测输入是否来自管道。
sys.stdin.isatty()
如果输入来自管道,则返回false,否则返回true。