概要
ちょっとしたツールやスクリプトを作りたいとき、Pythonで組むことが多いです。Windowsのバッチ、Shell Scriptでは機能不足もしくは、実現できるけれどもかなり無理やりな方法になる場合は、Pythonスクリプトで組みます。このときに使用しているスクリプトファイルのテンプレートを紹介します。
他のコマンドと連携できるよう、標準入力、標準出力を使ったり、コマンドライン引数でファイル指定できるようにしています。
スクリプト
- 1 コマンドライン引数があればそれを使う(ファイル名指定など)
- 2 1がなければ、標準入力をデータとして使う
- 3 1, 2がなければ標準入力を待ち受ける
- コマンドライン引数のクラス
argsの定義を書けるようにした
ソースコード
simple.py
import argparse
import sys
from dataclasses import dataclass
@dataclass
class SimpleArgs(object):
"""Args"""
input_data: str | None
def main():
"""simple"""
# コマンドライン引数設定
parser = argparse.ArgumentParser()
parser.add_argument(
'input_data',
nargs='?',
default=None,
help="ファイル名"
)
args = parser.parse_args() # type: SimpleArgs
args_input: str | None = None
pipe_input = None
stdin_input: list[str] = []
# 1. 位置引数があればファイル名が指定されたこととする
# 2. 1がなければ標準入力をデータとして使う
# 3. 1, 2がなければ標準入力を待ち受ける
if args.input_data:
args_input = args.input_data
elif not sys.stdin.isatty():
pipe_input = sys.stdin.read().strip()
else:
for line in sys.stdin:
stdin_input.append(line)
print("args_input: " + str(args_input))
print("pipe_input: " + str(pipe_input))
print("inputs: " + str(stdin_input))
print("ERROR: エラー出力サンプル" file=sys.stderr)
if __name__ == "__main__":
main()
実行例
以下は実行例です。
コマンドライン引数を指定したとき。
python sample.py input.csv
# 出力例
# args_input: input.csv
# pipe_input: None
# inputs: []
# ERROR: エラー出力サンプル
標準入力を与えたとき。
input.csv
id,name
123,hello
456,world
python sample.py <input.csv
# 出力例
# args_input: None
# pipe_input: id,name
# 123,hello
# 456,world
# inputs: []
# ERROR: エラー出力サンプル
パイプで標準入力を与えたとき。
echo "sample data" | python sample.py
# 出力例
# args_input: None
# pipe_input: sample data
# inputs: []
# ERROR: エラー出力サンプル
Git Bash for Windowsの場合
WindowsのGit Bash上でPythonを実行する際、標準入力、標準出力、パイプで渡す等した場合、Shift_JISでやり取りするので、文字化けする場合があります。
file input2.csv
# input2.csv: Unicode text, UTF-8 text
cat input2.csv
# id,name
# 123,こんにちは
# 456,世界
以下、文字化けが起きている例。
python sample.py <input2.csv
# 出力例
# args_input: None
# pipe_input: id,name
# 123,縺薙s縺ォ縺。縺ッ
# 456,荳也阜
# inputs: []
# ERROR: エラー出力サンプル
echo "サンプルデータ" | python sample.py
# 出力例
# args_input: None
# pipe_input: 繧オ繝ウ繝励Ν繝�繝シ繧ソ
# inputs: []
# ERROR: エラー出力サンプル
# 標準出力もShift_JISとなる
python sample.py input2.csv >output.txt
file output.txt
# output.txt: Non-ISO extended-ASCII text, with CRLF line terminators
cat output.txt
# args_input: input2.csv
# pipe_input: None
# inputs: []
# ERROR: □G□□□[□o□̓T□□□v□□
以下のように、UTF-8でやり取りするように環境変数でPythonへ知らせることで回避します。
PYTHONIOENCODING=utf8 python sample.py <input2.csv
# args_input: None
# pipe_input: id,name
# 123,こんにちは
# 456,世界
# inputs: []
# ERROR: エラー出力サンプル
echo "サンプルデータ" | PYTHONIOENCODING=utf8 python sample.py
# args_input: None
# pipe_input: サンプルデータ
# inputs: []
# ERROR: エラー出力サンプル
PYTHONIOENCODING=utf8 python sample.py input2.csv >output.txt
file output.txt
# output.txt: Unicode text, UTF-8 text, with CRLF line terminators
cat output.txt
# args_input: input2.csv
# pipe_input: None
# inputs: []
# ERROR: エラー出力サンプル
また、標準出力だけ文字化けを直したいという場合では、以下のようにiconvなどで変換するという手もあります。
python sample.py input2.csv | iconv -f cp932 -t utf-8
# args_input: input2.csv
# pipe_input: None
# inputs: []
# ERROR: エラー出力サンプル