Rya*_*rio 59 python command-line stdin arguments file
我编写了一个命令行实用程序,它使用getopt来解析命令行中给出的参数.我还希望有一个文件名是一个可选参数,比如它在其他实用程序中,如grep,cut等.所以,我希望它具有以下用法
tool -d character -f integer [filename]
Run Code Online (Sandbox Code Playgroud)
我该如何实施以下内容?
Sim*_*onJ 74
该的FileInput模块可以做你想做的-假设非选项参数是args
那么:
import fileinput
for line in fileinput.input(args):
print line
Run Code Online (Sandbox Code Playgroud)
如果args
为空fileinput.input()
则将从stdin读取; 否则它会以与Perl类似的方式依次从每个文件中读取while(<>)
.
Gre*_*ill 59
用最简单的术语来说:
import sys
# parse command line
if file_name_given:
inf = open(file_name_given)
else:
inf = sys.stdin
Run Code Online (Sandbox Code Playgroud)
此时您将使用inf
从文件中读取.根据是否给出文件名,这将从给定文件或stdin读取.
当您需要关闭文件时,您可以这样做:
if inf is not sys.stdin:
inf.close()
Run Code Online (Sandbox Code Playgroud)
但是,在大多数情况下,sys.stdin
如果你已经完成它将是无害的.
tri*_*eee 16
我喜欢使用上下文管理器的一般习惯用法,但是sys.stdin
当你离开with
语句时,(太)琐碎的解决方案最终会关闭,我想避免.
借用这个答案,这是一个解决方法:
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)
Run Code Online (Sandbox Code Playgroud)
我想你可以实现类似的东西,os.dup()
但我做的代码变得更复杂,更神奇,而上面有些笨重但非常直接.
Rou*_*oun 11
要使用python的with
语句,可以使用以下代码:
import sys
with open(sys.argv[1], 'r') if len(sys.argv) > 1 else sys.stdin as f:
# read data using f
# ......
Run Code Online (Sandbox Code Playgroud)
Phi*_* L. 10
我更喜欢使用" - "作为你应该从stdin读取的指标,它更明确:
import sys
with open(sys.argv[1], 'r') if sys.argv[1] is not "-" else sys.stdin as f:
pass # do something here
Run Code Online (Sandbox Code Playgroud)
切换到argparse
(它也是标准库的一部分)并使用
argparse.FileType
带有默认值 stdin 的 an :
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())
Run Code Online (Sandbox Code Playgroud)
但是,这不会让您为 stdin 指定编码和其他参数;如果你想这样做,你需要使参数成为非可选的,并让当作为参数给出FileType
时使用 stdin 来做它的事情:-
p.add_argument('input', type=FileType(encoding='UTF-8'))
Run Code Online (Sandbox Code Playgroud)
请注意,后一种情况将不支持二进制模式 ( 'b'
) I/O。如果您只需要这个,您可以使用上面的默认参数技术,但提取二进制 I/O 对象,例如default=sys.stdout.buffer
stdout。但是,如果用户-
无论如何指定,这仍然会中断。(对于-
stdin/stdout 总是用 包裹起来TextIOWrapper
。)
如果您希望它与 一起使用-
,或者在打开文件时需要提供任何其他参数,则可以修复参数(如果包装错误):
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
Run Code Online (Sandbox Code Playgroud)
(向medhat致敬,提及add_argument()
的type
参数。)
不是直接的答案,而是相关的。
通常,当您编写python脚本时,可以使用该argparse
软件包。在这种情况下,您可以使用:
parser = argparse.ArgumentParser()
parser.add_argument('infile', nargs='?', type=argparse.FileType('r'), default=sys.stdin)
Run Code Online (Sandbox Code Playgroud)
'?' 如果可能,将从命令行使用一个参数,并将其作为单个项目产生。如果不存在命令行参数,则将生成默认值。
在这里我们将默认设置为sys.stdin
;
因此,如果有一个文件,它将读取它,如果没有,它将从stdin中获取输入“注意:在上面的示例中,我们正在使用位置参数”
欲了解更多信息,请访问:https : //docs.python.org/2/library/argparse.html#nargs
归档时间: |
|
查看次数: |
59407 次 |
最近记录: |