LoginSignup
1
7

More than 5 years have passed since last update.

Python fileinput と argparse の両立

Posted at

たとえば、Perl で以下のように書くととても便利です。

while(<>){
    print $_;
}

何が便利かというと、以下2種類からの入力を受け付けられます。

  • 標準入力からの読み込み
  • 引数に指定したファイルの読み込み

Python で同じことは fileinput を使うとできるようです。

#!/usr/bin/env python
import fileinput

for line in fileinput.input():
    print(line, end="")

ここで、fileinputargparse と単純に組み合わせてみます。

#!/usr/bin/env python

import argparse
import fileinput

parser = argparse.ArgumentParser(prog="cata.py", description="fileinput & argparse")
parser.add_argument('-i', '--info', action='store_true', help='Print information')
args = parser.parse_args()

for line in fileinput.input():
    print(line, end="")

するとこんなエラーが(泣)

$ ./catf_ng.py  file?.txt
usage: cata.py [-h] [-i]
cata.py: error: unrecognized arguments: file0.txt file1.txt file2.txt

解決方法が下記のサイトにありました:grinning:
https://gist.github.com/martinth/ed991fb8cdcac3dfadf7

上記サイトには最終的な記述例が無かったのと、同様の内容が日本語サイトでヒットしなかったで、この記事にてメモを残したいと思います。

#!/usr/bin/env python

import argparse
import fileinput

parser = argparse.ArgumentParser(prog="cata.py", description="fileinput & argparse")
parser.add_argument('files', metavar='FILE', nargs='*', help='files to read, if empty, stdin is used')
parser.add_argument('-i', '--info', action='store_true', help='Print information')
args = parser.parse_args()

for line in fileinput.input(files=args.files):
    print(line, end="")

最後におまけで、上記add_argument()で追加したオプション('-i', '--info')で機能を追加してみました。

#!/usr/bin/env python

import argparse
import fileinput

parser = argparse.ArgumentParser(prog="cati.py", description="cat with file infomation")
parser.add_argument('files', metavar='FILE', nargs='*', help='files to read, if empty, stdin is used')
parser.add_argument('-i', '--info', action='store_true', help='Print filename and line no')
args = parser.parse_args()

for line in fileinput.input(files=args.files):
    if(args.info):
        if(fileinput.isfirstline()):
            print("*** {}".format(fileinput.filename()))
        print("{:6}\t".format(fileinput.filelineno()), end="")
    print(line, end="")

上記スクリプトはオプション無しだと cat だけします。
たとえば、以下3つのファイルを用意します。

file0.txt
I am Nozomi.
Are you Nozomi.
Yes, I am.

file1.txt
This is my bag.
That is your pen.
Is that a pen?
Yes, it is.
No, it is not.
It is a pencil.

file2.txt
He is my friend.
She is not from America.
Do you study English?
I like soccer.

"--info"または "-i" をつけて実行すると以下のように出力します。

$ ./cati.py --info file?.txt
*** file0.txt
     1  I am Nozomi.
     2  Are you Nozomi.
     3  Yes, I am.
     4  
*** file1.txt
     1  This is my bag.
     2  That is your pen.
     3  Is that a pen?
     4  Yes, it is.
     5  No, it is not.
     6  It is a pencil.
     7  
*** file2.txt
     1  He is my friend.
     2  She is not from America.
     3  Do you study English?
     4  I like soccer.
     5  
1
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
7