如果在Python中没有数据传输,如何从stdin或文件中读取?

e-s*_*tis 17 python stdin pipe command-line-interface

我有一个CLI脚本,希望它从文件中读取数据.它应该能够以两种方式阅读:

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

- 有点像grep,例如.

我知道的:

  • sys.argvoptparse让我轻松地阅读任何指定参数和选项.
  • sys.stdin 让我读一下管道传输的数据
  • fileinput 使整个过程自动化

不幸:

  • 使用fileinputstdin和任何args作为输入.所以我不能使用非文件名的选项,因为它试图打开它们.
  • sys.stdin.readlines() 工作正常,但如果我不管道任何数据,它会挂起,直到我进入 Ctrl + D
  • 我不知道如何实现"如果没有在stdin中,从args中的文件读取"因为stdin总是True在布尔上下文中.

如果可能的话,我想以便携的方式做到这一点.

syk*_*ora 20

Argparse允许以相当简单的方式完成此操作,optparse除非您遇到兼容性问题,否则您应该使用它.

代码将是这样的:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--input', type = argparse.FileType('r'), default = '-')
Run Code Online (Sandbox Code Playgroud)

现在你有一个解析你的命令行参数的解析器,如果它看到一个文件就使用它,或者如果没有则使用标准输入.

  • 或者您可以这样做:parser.add_argument(' - input',dest = input,type = file),因为FileType('R')将在之后为您打开一个打开的文件.您可以检查是否args.input,如果没有,则从stdin读取. (2认同)

And*_*ett 10

处理你想要的非文件名参数,所以最后得到一个非选项参数数组,然后将该数组作为参数传递给fileinput.input():

import fileinput
for line in fileinput.input(remaining_args):
    process(line)
Run Code Online (Sandbox Code Playgroud)


Joh*_*ooy 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
Run Code Online (Sandbox Code Playgroud)

我不确定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
Run Code Online (Sandbox Code Playgroud)

也许它对窗户来说并非毫无希望