我编写了一个命令行实用程序,它使用getopt来解析命令行中给出的参数。我也希望有一个文件名是一个可选参数,比如它在其他实用程序中,如grep,cut等。所以,我希望它具有以下用法
tool -d character -f integer [filename]
如何实施以下内容?
答案 0 :(得分:72)
fileinput模块可以做你想要的 - 假设非选项参数在args
中,那么:
import fileinput
for line in fileinput.input(args):
print line
如果args
为空,则fileinput.input()
将从标准输入读取;否则它会以与Perl的while(<>)
类似的方式依次从每个文件中读取。
答案 1 :(得分:56)
用最简单的术语来说:
import sys
# parse command line
if file_name_given:
inf = open(file_name_given)
else:
inf = sys.stdin
此时,您将使用inf
从文件中读取。根据是否给出文件名,这将从给定文件或stdin中读取。
当您需要关闭文件时,您可以执行以下操作:
if inf is not sys.stdin:
inf.close()
但是,在大多数情况下,如果您已完成此操作,则关闭sys.stdin
将无害。
答案 2 :(得分:15)
我喜欢使用上下文管理器的一般习惯用法,但是当你离开我想避免的sys.stdin
语句时,(太)琐碎的解决方案最终会关闭with
。
借用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()
但是我做的那些代码变得更复杂,更神奇,而上面的内容有点笨拙而且非常简单。
答案 3 :(得分:10)
要使用python的with
语句,可以使用以下代码:
import sys
with open(sys.argv[1], 'r') if len(sys.argv) > 1 else sys.stdin as f:
# read data using f
# ......
答案 4 :(得分:9)
我更喜欢使用“ - ”作为你应该从stdin读取的指标,它更明确:
import sys
with open(sys.argv[1], 'r') if sys.argv[1] is not "-" else sys.stdin as f:
pass # do something here
答案 5 :(得分:5)
不是直接的答案,而是相关的。
通常在编写python脚本时可以使用argparse
包。
如果是这种情况,您可以使用:
parser = argparse.ArgumentParser()
parser.add_argument('infile', nargs='?', type=argparse.FileType('r'), default=sys.stdin)
&#39;&#39 ;.如果可能,将从命令行使用一个参数, 并作为单个项目生产。如果不存在命令行参数, 将生成默认值。
这里我们将默认设置为sys.stdin
;
所以如果有一个文件它将读取它,如果没有它将从stdin&#34获取输入;注意:我们在上面的例子中使用位置参数&#34;
答案 6 :(得分:1)
类似的东西:
if input_from_file:
f = open(file_name, "rt")
else:
f = sys.stdin
inL = f.readline()
while inL:
print inL.rstrip()
inL = f.readline()
答案 7 :(得分:0)
切换到argparse
(它也是标准库的一部分)并使用
argparse.FileType
,默认值为stdin:
import argparse, sys
p = argparse.ArgumentParser()
p.add_argument('input', nargs='?',
type=argparse.FileType(), default=sys.stdin)
args = p.parse_args()
print(args.input.readlines())
这将不允许您为stdin指定编码和其他参数,
然而;如果要这样做,则需要使参数为非可选
并将FileType
设置为{
参数:
-
请注意,后一种情况将不支持二进制模式(p.add_argument('input', type=FileType(encoding='UTF-8'))
)I / O。如果
您只需要 即可使用上面的默认参数技术,但是
提取二进制I / O对象,例如'b'
标准输出。但是,如果用户仍然指定default=sys.stdout.buffer
,这仍然会中断。
(对于-
,stdin / stdout始终包裹在-
中。)
如果您希望它与TextIOWrapper
一起使用,或者需要任何其他参数,
在打开文件时提供,如果文件被包裹,则可以修复该参数
错误:
-
(medhat的提示)
提到p.add_argument('output', type=argparse.FileType('wb'))
args = p.parse_args()
if hasattr(args.output, 'buffer'):
# If the argument was '-', FileType('wb') ignores the 'b' when
# wrapping stdout. Fix that by grabbing the underlying binary writer.
args.output = args.output.buffer
的{{1}}参数。)