72

コマンドラインで指定された引数を解析するためにgetoptを使用するコマンドラインユーティリティを作成しました。また、grep、cutなどの他のユーティリティにあるような、ファイル名をオプションの引数にしたいので、次のように使用したいと思います。

tool -d character -f integer [filename]

どうすれば以下を実装できますか?

  • ファイル名が指定されている場合は、ファイルから読み取ります。
  • ファイル名が指定されていない場合は、STDINから読み取ります。
4

8 に答える 8

86

fileinputモジュールは、オプション以外の引数が含まれていると仮定して、必要な処理を実行できますargs

import fileinput
for line in fileinput.input(args):
    print line

args空の場合fileinput.input()、stdinから読み取ります。それ以外の場合は、Perlと同様に、各ファイルから順番に読み取りますwhile(<>)

于 2009-11-16T21:35:51.240 に答える
68

簡単に言えば:

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終わったら閉じるのは無害です。

于 2009-11-16T21:40:54.830 に答える
20

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 != '-':
            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)

と似たようなos.dup()ことを達成できると思いますが、それを実行するために作成したコードは、より複雑で魔法のようになりました。一方、上記はやや不格好ですが、非常に単純です。

于 2015-04-23T12:53:48.360 に答える
15

stdinから読み取る必要があることを示すインジケーターとして「-」を使用することを好みます。これは、より明確です。

import sys
with open(sys.argv[1], 'r') if sys.argv[1] is not "-" else sys.stdin as f:
    pass # do something here
于 2015-01-25T21:00:51.830 に答える
14

Pythonのwithステートメントを利用するには、次のコードを使用できます。

import sys
with open(sys.argv[1], 'r') if len(sys.argv) > 1 else sys.stdin as f:
    # read data using f
    # ......
于 2013-11-06T01:49:06.857 に答える
10

直接的な答えではありませんが、関連しています。

argparse通常、Pythonスクリプトを作成するときは、パッケージを使用できます。この場合、次を使用できます。

parser = argparse.ArgumentParser()
parser.add_argument('infile', nargs='?', type=argparse.FileType('r'), default=sys.stdin)

'?'。可能であれば、1つの引数がコマンドラインから消費され、単一のアイテムとして生成されます。コマンドライン引数が存在しない場合、デフォルトの値が生成されます。

ここでは、デフォルトをsys.stdin;に設定します。

したがって、ファイルがある場合はそれを読み取り、ない場合はstdinからの入力を受け取ります「注:上記の例では位置引数を使用していることに注意してください」

詳細については、 https://docs.python.org/2/library/argparse.html#nargsをご覧ください。

于 2018-05-24T09:11:52.273 に答える
3

argparse(これも標準ライブラリの一部です)に切り替えて、デフォルト値のstdinでを使用し ますargparse.FileType

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ときにstdinでそれをやらせる必要があります:-

p.add_argument('input', type=FileType(encoding='UTF-8'))

'b'この後者の場合は、バイナリモード( )I/Oを尊重しないことに注意してください。それだけが必要な場合は、上記のデフォルトの引数手法を使用できますが、たとえばdefault=sys.stdout.bufferstdoutのバイナリI/Oオブジェクトを抽出します。-ただし、ユーザーがとにかく指定した場合、これはまだ壊れます。(-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

(のパラメータについて言及するためのmedhatへのハットチップ。)add_argument()type

于 2020-09-03T03:40:58.117 に答える
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()
于 2009-11-16T21:54:11.047 に答える