記憶力が無い

プログラミングとランニングとカメラと何か

Python3で自作コマンドを作成する話

今更ながら Python で自作コマンドを作る方法を覚えたのでメモ。

概要

コマンド本体

import sys
import argparse


def get_parser():
    parser = argparse.ArgumentParser()
    parser.add_argument('FILE', nargs='*', default=['-'])
    return parser


def cat(file):
    line = file.readline()
    while line:
        print(line, end='')
        line = file.readline()


def process(file_name):
    if file_name == '-':
        cat(sys.stdin)
    else:
        with open(file_name, 'r') as file:
            cat(file)


def main():
    parser = get_parser()
    args = parser.parse_args()
    for file_name in args.FILE:
        process(file_name)

main 関数がコマンドの起点で、argparse を使い引数をパースし、受け取ったファイル名を process 関数に渡します。 process 関数は file_name- の時は標準入力を、それ以外の時はファイルの中身を読み標準出力に書き込みます。

argpase の引数の設定で parser.add_argument('FILE', nargs='*', default=['-']) としているため、ファイル名は複数指定することが出来きます。また、指定しなかった場合は標準入力 - が指定されるようになっています。

setup.py

setup.pypip install などを実行したときに読み込まれる設定ファイルです。

#!/bin/env python

from setuptools import setup

setup(
    name='tamacat',
    version='1.0.0',
    packages=['tamacat'],
    entry_points={
        'console_scripts': [
            'tamacat = tamacat.main:main'
        ]
    }
)

上記の内容を setup.py という名前で作成します。 setup には他にも指定できるオプションがありますが、今回は最低限のもののみを指定します。

    entry_points={
        'console_scripts': [
            'tamacat = tamacat.main:main'
        ]
    }

この部分が、tamacat コマンドが呼び出されたときに tamacat.main に記述した main 関数が呼び出されることを宣言しています。

ディレクトリ構成

project/
  ├ setup.py
  └ tamacat/
       ├ __init__.py
       └ main.py # コマンド本体

ディレクトリ構成はこのようにします。main.py に上に書いたコマンド本体を記述します。 __init__.pytamacat/ がモジュールであることを表すファイルです。今回はそれ以外に用途は無いので空のままにしておきます。

インストール

# プロジェクト直下で
pip install .
# もしくは
python3 -m pip install .

コマンドの動作確認

ファイル一つ

$ echo 'hello!' > hoge
$ tamacat hoge
hello!

ファイル複数

$ echo 'hello!' > hoge2
$ tamacat hoge*
hello!
hello!

標準出力

$ echo 'hello!' | tamacat
hello!

まとめ

ちょっとした CLI ツールならこんな感じでチャチャっと作ってしまえそうですね。

今回作ったコマンドは↓に置いておきます。参考までに。

github.com

Copyright © 2017 ttk1