これまで、「The Python Tutorial」の内容を紹介するかたちでPythonの機能や使い方を紹介してきた。チュートリアルにはまだ先があるのだが、残りの章で取り上げている内容は高度なプログラミングの話になってくるので、この連載の守備範囲を越えてくる。前回までの内容を把握してけば十分だろう。そこで今回は、Pythonを使って実際に自動作業ツールを作る例を取り上げる。

CSVデータを扱う

Pythonには、標準ライブラリにCSVデータを扱うためのモジュールが用意されている。「csv」というモジュールだ。このモジュールを利用すると、CSVデータをリストにしたり、リストをCSVデータとしてファイルに書き出すといったことを簡単に行える。

まず、例として次のようなCSVデータ「addresses.csv」を用意した。これは郵便番号データの一部だ。

13101,"100  ","1000000","トウキョウト","チヨダク","イカニケイサイガナイバアイ","東京都","千代田区","以下に掲載がない場合",0,0,0,0,0,0
13101,"102  ","1020072","トウキョウト","チヨダク","イイダバシ","東京都","千代田区","飯田橋",0,0,1,0,0,0
13101,"102  ","1020082","トウキョウト","チヨダク","イチバンチョウ","東京都","千代田区","一番町",0,0,0,0,0,0
13101,"101  ","1010032","トウキョウト","チヨダク","イワモトチョウ","東京都","千代田区","岩本町",0,0,1,0,0,0
13101,"101  ","1010047","トウキョウト","チヨダク","ウチカンダ","東京都","千代田区","内神田",0,0,1,0,0,0
13101,"100  ","1000011","トウキョウト","チヨダク","ウチサイワイチョウ","東京都","千代田区","内幸町",0,0,1,0,0,0
13101,"100  ","1000004","トウキョウト","チヨダク","オオテマチ(ツギノビルヲノゾク)","東京都","千代田区","大手町(次のビルを除く)",0,0,1,0,0,0
13101,"100  ","1006890","トウキョウト","チヨダク","オオテマチジェイエイビル(チカイ・カイソウフメイ)","東京都","千代田区","大手町JAビル(地階・階層不明)",0,0,0,0,0,0
13101,"100  ","1006801","トウキョウト","チヨダク","オオテマチジェイエイビル(1カイ)","東京都","千代田区","大手町JAビル(1階)",0,0,0,0,0,0
13101,"100  ","1006802","トウキョウト","チヨダク","オオテマチジェイエイビル(2カイ)","東京都","千代田区","大手町JAビル(2階)",0,0,0,0,0,0
13101,"100  ","1006803","トウキョウト","チヨダク","オオテマチジェイエイビル(3カイ)","東京都","千代田区","大手町JAビル(3階)",0,0,0,0,0,0
13101,"100  ","1006804","トウキョウト","チヨダク","オオテマチジェイエイビル(4カイ)","東京都","千代田区","大手町JAビル(4階)",0,0,0,0,0,0
13101,"100  ","1006805","トウキョウト","チヨダク","オオテマチジェイエイビル(5カイ)","東京都","千代田区","大手町JAビル(5階)",0,0,0,0,0,0
13101,"100  ","1006806","トウキョウト","チヨダク","オオテマチジェイエイビル(6カイ)","東京都","千代田区","大手町JAビル(6階)",0,0,0,0,0,0
13101,"100  ","1006807","トウキョウト","チヨダク","オオテマチジェイエイビル(7カイ)","東京都","千代田区","大手町JAビル(7階)",0,0,0,0,0,0
13101,"100  ","1006808","トウキョウト","チヨダク","オオテマチジェイエイビル(8カイ)","東京都","千代田区","大手町JAビル(8階)",0,0,0,0,0,0
13101,"100  ","1006809","トウキョウト","チヨダク","オオテマチジェイエイビル(9カイ)","東京都","千代田区","大手町JAビル(9階)",0,0,0,0,0,0
13101,"100  ","1006810","トウキョウト","チヨダク","オオテマチジェイエイビル(10カイ)","東京都","千代田区","大手町JAビル(10階)",0,0,0,0,0,0
13101,"100  ","1006811","トウキョウト","チヨダク","オオテマチジェイエイビル(11カイ)","東京都","千代田区","大手町JAビル(11階)",0,0,0,0,0,0
13101,"100  ","1006812","トウキョウト","チヨダク","オオテマチジェイエイビル(12カイ)","東京都","千代田区","大手町JAビル(12階)",0,0,0,0,0,0

注目したいのは、「データはカンマで区切られていること」「テキストデータはダブルクォーテーションで区切られていること(ただし、ダブルクォーテーション自体はデータそのものとしては扱われない)」「データに空白も含まれていること」などだ。

CSVはカンマで区切られたデータで、Microsoft Excelのデータをほかのプログラムで処理する場合など、何かと使われることの多いフォーマットだ。フォーマットの仕組みそのものはそれほど複雑なものではないのだが、クォーテーションまで含めてちゃんと処理しようとすると、自前でパーサを書くのはちょっと面倒だったりする。ここでcsvモジュールを使用すると、そうした部分をあまり気にすることなく処理が行えるようになる。

CSVデータの読み込み

csvモジュールに関しては「csv — CSV File Reading and Writing」に簡単な説明が掲載されている。基本的にはここに書いてある説明やサンプルコードを参考にしつつ、これまでチュートリアルで取り上げてきた内容を使えばそこそこのツールを作成することができる。

次に示すスクリプト「csv_read.py」は、ファイルからCSVデータを読み込んでリストで保持し、それを標準出力へ出力するというものだ。

#!/usr/bin/env python3

import csv

with open('addresses.csv') as fp:
    reader = csv.reader(fp)
    for row in reader:
        for i in range(0,4):
            print('[' + row[i] + ']', end='')
        print()

ファイルを開いたらcsv.reader()でCSVデータを読み込むオブジェクトを取得することができる。これをfor文で回して行ごとにリストデータを取得し、そこから先頭4列だけ出力するといった内容になっている。

csv_read.pyを実行すると次のようになる。

$ ./csv_read.py addresses.csv
[13101][100  ][1000000][トウキョウト]
[13101][102  ][1020072][トウキョウト]
[13101][102  ][1020082][トウキョウト]
[13101][101  ][1010032][トウキョウト]
[13101][101  ][1010047][トウキョウト]
[13101][100  ][1000011][トウキョウト]
[13101][100  ][1000004][トウキョウト]
[13101][100  ][1006890][トウキョウト]
[13101][100  ][1006801][トウキョウト]
[13101][100  ][1006802][トウキョウト]
[13101][100  ][1006803][トウキョウト]
[13101][100  ][1006804][トウキョウト]
[13101][100  ][1006805][トウキョウト]
[13101][100  ][1006806][トウキョウト]
[13101][100  ][1006807][トウキョウト]
[13101][100  ][1006808][トウキョウト]
[13101][100  ][1006809][トウキョウト]
[13101][100  ][1006810][トウキョウト]
[13101][100  ][1006811][トウキョウト]
[13101][100  ][1006812][トウキョウト]
$

CSVデータをちゃんと理解してリストに展開していることがわかる。これだけだが、自分でCSVパーサを書く必要がなくなるので便利だ。

CSVデータの書き込み

次のサンプル「csv_write.py」は、CSVデータを書き込む例だ。出力先を標準出力にしてあるので、実行すると標準出力にCSVデータが出力される。csv.writer()でCSVデータのライタオブジェクトが取得できる辺りがポイントである。

#!/usr/bin/env python3

import csv

# 住所データをリストで用意
address1 = [13101,"100  ","1000000","トウキョウト"]
address2 = [13101,"102  ","1020072","トウキョウト"]
address3 = [13101,"102  ","1020082","トウキョウト"]

addresses = [[13101,"100  ","1000000","トウキョウト"],
             [13101,"102  ","1020072","トウキョウト"],
             [13101,"102  ","1020082","トウキョウト"],
             [13101,"101  ","1010032","トウキョウト"],
             [13101,"101  ","1010047","トウキョウト"],
             [13101,"100  ","1000011","トウキョウト"],
             [13101,"100  ","1000004","トウキョウト"],
             [13101,"100  ","1006890","トウキョウト"],
             [13101,"100  ","1006801","トウキョウト"],
             [13101,"100  ","1006802","トウキョウト"],
             [13101,"100  ","1006803","トウキョウト"],
             [13101,"100  ","1006804","トウキョウト"],
             [13101,"100  ","1006805","トウキョウト"],
             [13101,"100  ","1006806","トウキョウト"],
             [13101,"100  ","1006807","トウキョウト"],
             [13101,"100  ","1006808","トウキョウト"],
             [13101,"100  ","1006809","トウキョウト"],
             [13101,"100  ","1006810","トウキョウト"],
             [13101,"100  ","1006811","トウキョウト"],
             [13101,"100  ","1006812","トウキョウト"]]

# 1行ずつCSVデータを出力
print('--')
with open('/dev/stdout', 'w') as fp:
    writer = csv.writer(fp)
    writer.writerow(address1)
    writer.writerow(address2)
    writer.writerow(address3)

# 複数行まとめてCSVデータを出力
print('--')
with open('/dev/stdout', 'w') as fp:
    writer = csv.writer(fp)
    writer.writerows(addresses)

# 複数行まとめて空白区切りにして出力
print('--')
with open('/dev/stdout', 'w') as fp:
    writer = csv.writer(fp, delimiter=' ')
    writer.writerows(addresses)

csv_write.pyを実行すると次のようになる。

% ./csv_write.py
--
13101,100  ,1000000,トウキョウト
13101,102  ,1020072,トウキョウト
13101,102  ,1020082,トウキョウト
--
13101,100  ,1000000,トウキョウト
13101,102  ,1020072,トウキョウト
13101,102  ,1020082,トウキョウト
13101,101  ,1010032,トウキョウト
13101,101  ,1010047,トウキョウト
13101,100  ,1000011,トウキョウト
13101,100  ,1000004,トウキョウト
13101,100  ,1006890,トウキョウト
13101,100  ,1006801,トウキョウト
13101,100  ,1006802,トウキョウト
13101,100  ,1006803,トウキョウト
13101,100  ,1006804,トウキョウト
13101,100  ,1006805,トウキョウト
13101,100  ,1006806,トウキョウト
13101,100  ,1006807,トウキョウト
13101,100  ,1006808,トウキョウト
13101,100  ,1006809,トウキョウト
13101,100  ,1006810,トウキョウト
13101,100  ,1006811,トウキョウト
13101,100  ,1006812,トウキョウト
--
13101 "100  " 1000000 トウキョウト
13101 "102  " 1020072 トウキョウト
13101 "102  " 1020082 トウキョウト
13101 "101  " 1010032 トウキョウト
13101 "101  " 1010047 トウキョウト
13101 "100  " 1000011 トウキョウト
13101 "100  " 1000004 トウキョウト
13101 "100  " 1006890 トウキョウト
13101 "100  " 1006801 トウキョウト
13101 "100  " 1006802 トウキョウト
13101 "100  " 1006803 トウキョウト
13101 "100  " 1006804 トウキョウト
13101 "100  " 1006805 トウキョウト
13101 "100  " 1006806 トウキョウト
13101 "100  " 1006807 トウキョウト
13101 "100  " 1006808 トウキョウト
13101 "100  " 1006809 トウキョウト
13101 "100  " 1006810 トウキョウト
13101 "100  " 1006811 トウキョウト
13101 "100  " 1006812 トウキョウト
%

リストをCSVデータ1行分として書き出すことができるほか、「リストのリスト」は複数行のCSVデータとして書き出せていることがわかる。また、デリミタを指定するとカンマ区切りではなく指定したデリミタ区切りで出力が行える点に注目したい。

例えば、カンマ区切りのままで出力している場合には、空白は処理する必要がないので何のクォート処理もされていない。しかし、デリミタとして空白を指定すると、データとしての空白をクォートする必要が出てくることから、2列目のデータがダブルクォーテーションでクォートされたことを確認できる。

自前でCSVデータを出力しようとすると、この辺りを自分でパース処理する必要があるが、csvモジュールを利用すればモジュール側で良い感じに処理してくれる。

csv2ssvコマンド

ここで用意した2つのサンプルコードを組み合わせるだけでも、ツールを作成することができる。例えば次のように書けば、CSVデータをSSVデータに変換するツールを作ることができる。SSVというのは空白区切りのデータのことだ。CSVがカンマ区切りであることに対し、SSVはカンマの部分が空白になる。

■ CSVデータをSSVデータに変換するツール(csv2ssv_proto1.py)

#!/usr/bin/env python3

import sys
import csv

with open('/dev/stdout', 'w') as fp_w:
    # SSVに変換したいためデリミタに空白を指定
    writer = csv.writer(fp_w, delimiter=' ')

    with open(sys.argv[1]) as fp_r:
        # 1行ずつ読み込んでSSVで出力
        reader = csv.reader(fp_r)
        for row in reader:
            writer.writerow(row)

このツールを実行すると次のようになる。

% ./csv2ssv_proto1.py addresses.csv
13101 "100  " 1000000 トウキョウト チヨダク イカニケイサイガナイバアイ 東京都 千代田区 以下に掲載がない場合 0 0 0 0 0 0
13101 "102  " 1020072 トウキョウト チヨダク イイダバシ 東京都 千代田区 飯田橋 0 0 1 0 0 0
13101 "102  " 1020082 トウキョウト チヨダク イチバンチョウ 東京都 千代田区 一番町 0 0 0 0 0 0
13101 "101  " 1010032 トウキョウト チヨダク イワモトチョウ 東京都 千代田区 岩本町 0 0 1 0 0 0
13101 "101  " 1010047 トウキョウト チヨダク ウチカンダ 東京都 千代田区 内神田 0 0 1 0 0 0
13101 "100  " 1000011 トウキョウト チヨダク ウチサイワイチョウ 東京都 千代田区 内幸町 0 0 1 0 0 0
13101 "100  " 1000004 トウキョウト チヨダク オオテマチ(ツギノビルヲノゾク) 東京都 千代田区 大手町(次のビルを除く) 0 0 1 0 0 0
13101 "100  " 1006890 トウキョウト チヨダク オオテマチジェイエイビル(チカイ・カイソウフメイ) 東京都 千代田区 大手町JAビル(地階・階層不明) 0 0 0 0 0 0
13101 "100  " 1006801 トウキョウト チヨダク オオテマチジェイエイビル(1カイ) 東京都 千代田区 大手町JAビル(1階) 0 0 0 0 0 0
13101 "100  " 1006802 トウキョウト チヨダク オオテマチジェイエイビル(2カイ) 東京都 千代田区 大手町JAビル(2階) 0 0 0 0 0 0
13101 "100  " 1006803 トウキョウト チヨダク オオテマチジェイエイビル(3カイ) 東京都 千代田区 大手町JAビル(3階) 0 0 0 0 0 0
13101 "100  " 1006804 トウキョウト チヨダク オオテマチジェイエイビル(4カイ) 東京都 千代田区 大手町JAビル(4階) 0 0 0 0 0 0
13101 "100  " 1006805 トウキョウト チヨダク オオテマチジェイエイビル(5カイ) 東京都 千代田区 大手町JAビル(5階) 0 0 0 0 0 0
13101 "100  " 1006806 トウキョウト チヨダク オオテマチジェイエイビル(6カイ) 東京都 千代田区 大手町JAビル(6階) 0 0 0 0 0 0
13101 "100  " 1006807 トウキョウト チヨダク オオテマチジェイエイビル(7カイ) 東京都 千代田区 大手町JAビル(7階) 0 0 0 0 0 0
13101 "100  " 1006808 トウキョウト チヨダク オオテマチジェイエイビル(8カイ) 東京都 千代田区 大手町JAビル(8階) 0 0 0 0 0 0
13101 "100  " 1006809 トウキョウト チヨダク オオテマチジェイエイビル(9カイ) 東京都 千代田区 大手町JAビル(9階) 0 0 0 0 0 0
13101 "100  " 1006810 トウキョウト チヨダク オオテマチジェイエイビル(10カイ) 東京都 千代田区 大手町JAビル(10階) 0 0 0 0 0 0
13101 "100  " 1006811 トウキョウト チヨダク オオテマチジェイエイビル(11カイ) 東京都 千代田区 大手町JAビル(11階) 0 0 0 0 0 0
13101 "100  " 1006812 トウキョウト チヨダク オオテマチジェイエイビル(12カイ) 東京都 千代田区 大手町JAビル(12階) 0 0 0 0 0 0
%

CSVデータがSSVデータに変換されていること、データとしての空白がクォート処理されていることが確認できる。

もうちょっとツールらしくスクリプトを書き換えてみよう。先程のコードだと、必ず引数にCSVファイルを指定する必要がある。だが、処理によってはパイプやシェルから標準入力経由でCSVデータを渡したいこともある。

そんな場合には、次のように引数指定に合わせて入力先を変えるように書き換えれば、引数でも標準入力からでもデータを処理できるようになる。

■ 引数指定に合わせて入力先を変えるように書き換えたスクリプト(csv2ssv.py)

#!/usr/bin/env python3

import sys
import csv

# 引数にファイルの指定がなければ標準入力を、
# ファイルが指定されている場合には指定されて
# いるファイルからデータを読み込む
fpath_i = '/dev/stdin'
if (1 < len(sys.argv)):
    fpath_i = sys.argv[1]

# 出力先は標準出力
fpath_o = '/dev/stdout'

with open(fpath_o, 'w') as fp_w:
    # SSVに変換したいためデリミタに空白を指定
    writer = csv.writer(fp_w, delimiter=' ')

    with open(fpath_i) as fp_r:
        # 1行ずつ読み込んでSSVで出力
        reader = csv.reader(fp_r)
        for row in reader:
            writer.writerow(row)

書き換えた上記スクリプトを実行すると次のようになる。

% cat addresses.csv | ./csv2ssv.py
13101 "100  " 1000000 トウキョウト チヨダク イカニケイサイガナイバアイ 東京都 千代田区 以下に掲載がない場合 0 0 0 0 0 0
13101 "102  " 1020072 トウキョウト チヨダク イイダバシ 東京都 千代田区 飯田橋 0 0 1 0 0 0
13101 "102  " 1020082 トウキョウト チヨダク イチバンチョウ 東京都 千代田区 一番町 0 0 0 0 0 0
13101 "101  " 1010032 トウキョウト チヨダク イワモトチョウ 東京都 千代田区 岩本町 0 0 1 0 0 0
13101 "101  " 1010047 トウキョウト チヨダク ウチカンダ 東京都 千代田区 内神田 0 0 1 0 0 0
13101 "100  " 1000011 トウキョウト チヨダク ウチサイワイチョウ 東京都 千代田区 内幸町 0 0 1 0 0 0
13101 "100  " 1000004 トウキョウト チヨダク オオテマチ(ツギノビルヲノゾク) 東京都 千代田区 大手町(次のビルを除く) 0 0 1 0 0 0
13101 "100  " 1006890 トウキョウト チヨダク オオテマチジェイエイビル(チカイ・カイソウフメイ) 東京都 千代田区 大手町JAビル(地階・階層不明) 0 0 0 0 0 0
13101 "100  " 1006801 トウキョウト チヨダク オオテマチジェイエイビル(1カイ) 東京都 千代田区 大手町JAビル(1階) 0 0 0 0 0 0
13101 "100  " 1006802 トウキョウト チヨダク オオテマチジェイエイビル(2カイ) 東京都 千代田区 大手町JAビル(2階) 0 0 0 0 0 0
13101 "100  " 1006803 トウキョウト チヨダク オオテマチジェイエイビル(3カイ) 東京都 千代田区 大手町JAビル(3階) 0 0 0 0 0 0
13101 "100  " 1006804 トウキョウト チヨダク オオテマチジェイエイビル(4カイ) 東京都 千代田区 大手町JAビル(4階) 0 0 0 0 0 0
13101 "100  " 1006805 トウキョウト チヨダク オオテマチジェイエイビル(5カイ) 東京都 千代田区 大手町JAビル(5階) 0 0 0 0 0 0
13101 "100  " 1006806 トウキョウト チヨダク オオテマチジェイエイビル(6カイ) 東京都 千代田区 大手町JAビル(6階) 0 0 0 0 0 0
13101 "100  " 1006807 トウキョウト チヨダク オオテマチジェイエイビル(7カイ) 東京都 千代田区 大手町JAビル(7階) 0 0 0 0 0 0
13101 "100  " 1006808 トウキョウト チヨダク オオテマチジェイエイビル(8カイ) 東京都 千代田区 大手町JAビル(8階) 0 0 0 0 0 0
13101 "100  " 1006809 トウキョウト チヨダク オオテマチジェイエイビル(9カイ) 東京都 千代田区 大手町JAビル(9階) 0 0 0 0 0 0
13101 "100  " 1006810 トウキョウト チヨダク オオテマチジェイエイビル(10カイ) 東京都 千代田区 大手町JAビル(10階) 0 0 0 0 0 0
13101 "100  " 1006811 トウキョウト チヨダク オオテマチジェイエイビル(11カイ) 東京都 千代田区 大手町JAビル(11階) 0 0 0 0 0 0
13101 "100  " 1006812 トウキョウト チヨダク オオテマチジェイエイビル(12カイ) 東京都 千代田区 大手町JAビル(12階) 0 0 0 0 0 0
% ./csv2ssv.py addresses.csv
13101 "100  " 1000000 トウキョウト チヨダク イカニケイサイガナイバアイ 東京都 千代田区 以下に掲載がない場合 0 0 0 0 0 0
13101 "102  " 1020072 トウキョウト チヨダク イイダバシ 東京都 千代田区 飯田橋 0 0 1 0 0 0
13101 "102  " 1020082 トウキョウト チヨダク イチバンチョウ 東京都 千代田区 一番町 0 0 0 0 0 0
13101 "101  " 1010032 トウキョウト チヨダク イワモトチョウ 東京都 千代田区 岩本町 0 0 1 0 0 0
13101 "101  " 1010047 トウキョウト チヨダク ウチカンダ 東京都 千代田区 内神田 0 0 1 0 0 0
13101 "100  " 1000011 トウキョウト チヨダク ウチサイワイチョウ 東京都 千代田区 内幸町 0 0 1 0 0 0
13101 "100  " 1000004 トウキョウト チヨダク オオテマチ(ツギノビルヲノゾク) 東京都 千代田区 大手町(次のビルを除く) 0 0 1 0 0 0
13101 "100  " 1006890 トウキョウト チヨダク オオテマチジェイエイビル(チカイ・カイソウフメイ) 東京都 千代田区 大手町JAビル(地階・階層不明) 0 0 0 0 0 0
13101 "100  " 1006801 トウキョウト チヨダク オオテマチジェイエイビル(1カイ) 東京都 千代田区 大手町JAビル(1階) 0 0 0 0 0 0
13101 "100  " 1006802 トウキョウト チヨダク オオテマチジェイエイビル(2カイ) 東京都 千代田区 大手町JAビル(2階) 0 0 0 0 0 0
13101 "100  " 1006803 トウキョウト チヨダク オオテマチジェイエイビル(3カイ) 東京都 千代田区 大手町JAビル(3階) 0 0 0 0 0 0
13101 "100  " 1006804 トウキョウト チヨダク オオテマチジェイエイビル(4カイ) 東京都 千代田区 大手町JAビル(4階) 0 0 0 0 0 0
13101 "100  " 1006805 トウキョウト チヨダク オオテマチジェイエイビル(5カイ) 東京都 千代田区 大手町JAビル(5階) 0 0 0 0 0 0
13101 "100  " 1006806 トウキョウト チヨダク オオテマチジェイエイビル(6カイ) 東京都 千代田区 大手町JAビル(6階) 0 0 0 0 0 0
13101 "100  " 1006807 トウキョウト チヨダク オオテマチジェイエイビル(7カイ) 東京都 千代田区 大手町JAビル(7階) 0 0 0 0 0 0
13101 "100  " 1006808 トウキョウト チヨダク オオテマチジェイエイビル(8カイ) 東京都 千代田区 大手町JAビル(8階) 0 0 0 0 0 0
13101 "100  " 1006809 トウキョウト チヨダク オオテマチジェイエイビル(9カイ) 東京都 千代田区 大手町JAビル(9階) 0 0 0 0 0 0
13101 "100  " 1006810 トウキョウト チヨダク オオテマチジェイエイビル(10カイ) 東京都 千代田区 大手町JAビル(10階) 0 0 0 0 0 0
13101 "100  " 1006811 トウキョウト チヨダク オオテマチジェイエイビル(11カイ) 東京都 千代田区 大手町JAビル(11階) 0 0 0 0 0 0
13101 "100  " 1006812 トウキョウト チヨダク オオテマチジェイエイビル(12カイ) 東京都 千代田区 大手町JAビル(12階) 0 0 0 0 0 0
%

引数にファイルが指定された場合でも、パイプ経由でデータが渡ってきた場合でも、両方とも処理できることがわかる。

こんな感じでPythonを使うと、かなり簡単にそこそこのツールを作成できることがおわかりいただけただろうか。プログラミングの経験がないと最初はもたつくかもしれないが、それでもほかのプログラミング言語と比べれば、かなり簡単だ。ここまでできるようになると、普段行っているLinuxでの作業のいくつかを自動化するためのツールとしてPythonを利用できるようになる。

参考資料