我已經編寫了一個命令行實用程序,它使用getopt來解析命令行中給出的參數。我也想有一個文件名是一個可選的參數,如它在其他實用程序,如grep,剪切等,所以,我想它有以下用途從文件讀取或STDIN
tool -d character -f integer [filename]
我如何能實現以下?
- 如果給出文件名,則從文件中讀取。
- 如果沒有給出文件名,則從STDIN中讀取。
我已經編寫了一個命令行實用程序,它使用getopt來解析命令行中給出的參數。我也想有一個文件名是一個可選的參數,如它在其他實用程序,如grep,剪切等,所以,我想它有以下用途從文件讀取或STDIN
tool -d character -f integer [filename]
我如何能實現以下?
簡單的說:
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