从文件或STDIN读取

我写了一个命令行实用程序,它使用getopt来parsing命令行中给出的参数。 我也想有一个文件名是一个可选的参数,如它在其他工具如grep,剪切等。所以,我希望它有以下用法

tool -d character -f integer [filename] 

我怎样才能实现以下?

  • 如果给出文件名,则从文件中读取。
  • 如果没有给出文件名,则从STDIN中读取。

最简单的说法是:

 import sys # parse command line if file_name_given: inf = open(file_name_given) else: inf = sys.stdin 

此时,您将使用inf从文件读取。 根据是否给出文件名,这将从给定的文件或标准input读取。

当你需要closures文件时,你可以这样做:

 if inf is not sys.stdin: inf.close() 

但是,在大多数情况下,closuressys.stdin是完全无害的。

fileinput模块可以做你想做的事情 – 假设非选项参数在args那么:

 import fileinput for line in fileinput.input(args): print line 

如果args为空,则fileinput.input()将从标准input读取; 否则它会依次读取每个文件,类似于Perl的while(<>)

我喜欢使用上下文pipe理器的一般习惯用法,但是当你不在with语句中时,(太)小问题的解决scheme最终会closuressys.stdin ,这是我想避免的。

从这个答案借用, 这是一个解决方法:

 import sys import contextlib @contextlib.contextmanager def _smart_open(filename, mode='Ur'): if filename == '-': if mode is None or mode == '' or 'r' in mode: fh = sys.stdin else: fh = sys.stdout else: fh = open(filename, mode) try: yield fh finally: if filename is not '-': fh.close() if __name__ == '__main__': args = sys.argv[1:] if args == []: args = ['-'] for filearg in args: with _smart_open(filearg) as handle: do_stuff(handle) 

我想你可以用os.dup()来实现类似的function,但是我准备做的代码变得更复杂,更神奇,而上面的代码有些笨重,但是很直接。

要使用Python的语句,可以使用下面的代码:

 import sys with open(sys.argv[1], 'r') if len(sys.argv) > 1 else sys.stdin as f: # read data using f # ...... 

我更喜欢使用“ – ”作为一个指标,你应该从标准input读取,这是更明确的:

 import sys with open(sys.argv[1], 'r') if sys.argv[1] is not "-" else sys.stdin as f: pass # do something here 

就像是:

 if input_from_file: f = open(file_name, "rt") else: f = sys.stdin inL = f.readline() while inL: print inL.rstrip() inL = f.readline()