web-dev-qa-db-ja.com

pythonプログラムを適切なUNIXツールのように動作させるにはどうすればよいですか?

私はいくつかのPythonスクリプトを配置していて、それらを書き直しているところです。すべて同じ問題があります。

適切なUNIXツールのように動作するようにプログラムを作成する方法は、私には明らかではありません。

これは

$ cat characters | progname

この

$ progname characters

同じ出力を生成する必要があります。

Pythonでそれを見つけることができた最も近いものはfileinputライブラリでした。残念ながら、私のPythonスクリプトをすべて書き直す方法は本当にわかりませんこれは次のようになります。

#!/usr/bin/env python 
# coding=UTF-8

import sys, re

for file in sys.argv[1:]:
    f = open(file)
    fs = f.read()
    regexnl = re.compile('[^\s\w.,?!:;-]')
    rstuff = regexnl.sub('', fs)
    f.close()
    print rstuff

Fileinputライブラリは、stdinがある場合はstdinを処理し、ファイルがある場合はファイルを処理します。 ただし、1行で繰り返します。

import fileinput
for line in fileinput.input():
    process(line)

本当にわかりません。小さなファイルを処理している場合、またはファイルに多くのことをしていない場合、これは明白に思えるかもしれません。しかし、私の目的では、これにより、上記のように単にファイル全体を開いて文字列に読み取るよりもはるかに遅くなります。

現在、上記のスクリプトを次のように実行します

$ pythonscript textfilename1 > textfilename2

しかし、私はそれ(とその兄弟)をパイプで実行できるようにしたいのですが、

$ grep pattern textfile1 | pythonscript | pythonscript | pythonscript > textfile2
26
ixtmixilix

なぜか

files = sys.argv[1:]
if not files:
    files = ["/dev/stdin"]

for file in files:
    f = open(file)
    ...
9
Mikel

ファイル名が引数として指定されているかどうかを確認するか、またはsys.stdin

このようなもの:

if sys.argv[1]:
   f = open(sys.argv[1])
else:
   f = sys.stdin 

sysモジュールを使用することを除いて、Mikelの回答に似ています。彼らがそこにそれを持っているなら、それは理由があるに違いない...

13
rahmu

私の好ましいやり方は...(そしてこれは Harbinger's Hollow と呼ばれる素敵なLinuxブログから取られたものです)

#!/usr/bin/env python

import argparse, sys

parser = argparse.ArgumentParser()
parser.add_argument('filename', nargs='?')
args = parser.parse_args()
if args.filename:
    string = open(args.filename).read()
Elif not sys.stdin.isatty():
    string = sys.stdin.read()
else:
    parser.print_help()

私がこれを最も気に入った理由は、ブロガーが言うように、誤って入力せずに呼び出された場合、ばかげたメッセージを出力するだけだからです。また、既存のすべてのPythonスクリプトにうまく組み込むことができるので、スクリプトを含めてすべて修正しました。

4
ixtmixilix
files=sys.argv[1:]

for f in files or [sys.stdin]:
   if isinstance(f, file):
      txt = f.read()
   else:
      txt = open(f).read()

   process(txt)
3
JJoao

私はこのソリューションを使用していて、それは魅力のように機能します。実際、私はスクリプトで使用しています naccent は、指定された文字列からアクセントを小文字にして削除します

argument = sys.argv[1:] if len(sys.argv) > 1 else sys.stdin.read()

私がこの解決策を目にした最もきつい時間は here だったと思います。

0
SergioAraujo

システムに/dev/stdinがない場合、またはより一般的な解決策が必要な場合は、次のようなより複雑な方法を試すことができます。

class Stdin(object):
    def __getattr__(self, attr):
        return getattr(sys.stdin, attr)

    def __enter__(self):
        return self

def myopen(path):
    if path == "-":
        return Stdin()
    return open(path)

for n in sys.argv[1:] or ["-"]:
    with myopen(n) as f:
            ...
0
Mikel