从文件读取或STDIN
我已经编写了一个命令行实用程序,它使用getopt来解析命令行中给出的参数。我也想有一个文件名是一个可选的参数,如它在其他实用程序,如grep,剪切等,所以,我想它有以下用途从文件读取或STDIN
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
从文件中读取。根据是否给出文件名,这将从给定文件或标准输入读取。
当您需要关闭文件,你可以这样做:
if inf is not sys.stdin:
inf.close()
然而,在大多数情况下,它是无害关闭sys.stdin
,如果你用它做。
raw_input()和input()会从inf中读取吗? – thefourtheye 2013-05-03 12:54:23
@thefourtheye:是的,这两个函数都会从文件或sys.stdin中读取。 – 2013-05-03 18:41:26
我发现了另一种解决这个问题的方法,我在http://dfourtheye.blogspot.in/2013/05/python-equivalent-of-cs-freopen.html这里发布了博客,并且也为这个问题添加了一个答案。 – thefourtheye 2013-05-04 02:16:48
的fileinput模块可以做你想做的 - 假设非选项参数是args
则:
import fileinput
for line in fileinput.input(args):
print line
如果args
为空,则fileinput.input()
会从标准输入读取;否则它会依次读取每个文件,与Perl的while(<>)
类似。
喜欢的东西:
if input_from_file:
f = open(file_name, "rt")
else:
f = sys.stdin
inL = f.readline()
while inL:
print inL.rstrip()
inL = f.readline()
要使用Python的with
语句,可以使用下面的代码:
import sys
with open(sys.argv[1], 'r') if len(sys.argv) > 1 else sys.stdin as f:
# read data using f
# ......
您的解决方案将关闭'sys.stdin',因此在'with'语句之后调用'input'函数会引发'ValueError'。 – 2015-05-24 15:42:32
我更愿意用“ - ”为你应该阅读的指标从stdin,它更明确:
import sys
with open(sys.argv[1], 'r') if sys.argv[1] is not "-" else sys.stdin as f:
pass # do something here
您的解决方案将关闭'sys.stdin',因此在'with'语句之后调用'input'函数会引发'ValueError'。 – 2015-05-24 15:42:27
@TimofeyBondarev这可能是正确的..但最常见的输入只在脚本中使用一次。这是一个有用的构造。 – javadba 2016-02-02 05:52:44
我喜欢使用上下文管理的一般习语呃,但是当你不在我想要避免的with
声明中时,(太)无效的解决方案最终会结束sys.stdin
。
从this answer借款,这里是一个解决办法:
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)
我想你可以实现something similar with os.dup()
,但我做了这样做竟然是更复杂,更神奇的代码,而上面是有点笨重但很直接。
非常感谢!这正是我正在寻找的。非常明确和直接的解决方案。 – edisonex 2017-11-15 13:43:20
另请参阅http://unix.stackexchange.com/questions/47098/how-do-i-make-python-programs-behave-like-proper-unix-tools/47543#47543 – magnetar 2012-09-08 12:18:22