从文件或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()