PythonでCSVファイルを1行ずつ読み込んでコマンド実行

IT/インターネット
スポンサーリンク

ちょっとしたスクリプトなんだけど一般的な御作法とかスッカリ忘れてしまったので、コアな処理部分だけじゃなくて、前後のお決まりコードなども含めて、思い出しがてら書き残しておく

スクリプト作成時に知っておくべきこと

冒頭に書いたお作法的なことを知らないで書いているのって… なんか… ダサいじゃん?w

よくあるのが、即興でパターン1で書き、書き換えているうちにパターン2,3となり、他のスクリプトからも利用したくなりパターン4に改良した、というケースです。

(snip)

Pythonファイルは、必ず__name__という属性を持ちます。そのファイルがプログラムとして起動されると'__main__'が値として代入されます。つまり、__name__ == '__main__'が成立する時は、プログラムとして起動しているので、main()を実行します。

(snip)

スクリプトはその場限りで作成することもよくあるので、パターン1や2を採用することが多いかもしれませんが、最終的には「パターン4」を用いることをお勧めします。

Pythonスクリプトの書き方(4パターン) – ガンマソフト株式会社

パターン1-4ってなんだ?って話だけど、その詳細はリンク先を見てもらうとして

以下のあたりも「なぜ?」の答えなので色々実装してみて経験から腹落ちできているといいよね

Python では本来 main 関数を定義する必要はありませんが、経験者が書いたスクリプトではよく main 関数が書かれています。 筆者は Python を学び始めた頃にそのようなコードを見て「必要ないものをなぜわざわざ書くのだろう?」と疑問に思いました。 今回は筆者自身がかつて抱いたこの疑問に答えてみます。

尚、 main という名前を使うのはただの慣習です。 この名前の関数にしないといけない制約は特にありません。

1. 関数の定義を後ろに書ける
2. 抽象度の高い処理の流れを main 関数で示せる
3. 処理の変更や差し替えがしやすい
4. テストが書きやすい
5. 変数名の意図しない衝突を防げる

Python Tips: Python で main 関数を定義することのメリット – Life with Python

__name____main__ の話

def main():
    print("Hello")

if __name__ == '__main__':
    main()

Shebangだったり文字コードの話だったり

コレのこと

#! /usr/bin/env python
# -*- coding: utf-8 -*-

Python3からは文字コードの指定は必要ないらしい…

Python3ではデフォルトのエンコードがUTF-8となっているのでこの対応は不要となっている(PEP 3120 — Using UTF-8 as the default source encoding)。

Pythonを書き始める前に見るべきTips – Qiita

Shebangは慣習的なことだし、文字コードの指定はPython2までの話だとすると、Python3を使う分には、これらの記述は不要ってことになるんじゃない?

このほか、コーディング規約のPEP8なんかも抑えておきたところ…

以下は、Pythonに関する色んな事が1つのページにまとまっている

ログも抑えておきたいねぇ

そもそものファイル操作の話とcsvを辞書型で読み取り

ファイル開いて、一気に全部読み込むか、1行ずつ読み込むか

ファイルをオープンした後、それを標準のcsvモジュールを使って辞書型(形式)でforループで1行ずつ処理するのが良さそう

Pythonでcsvデータを辞書形式で読み込む方法 – 知的好奇心

import csv
with open('data.csv', newline='') as csvfile:
    reader = csv.DictReader(csvfile)
    for row in reader:
        print(row)

OS毎に異なる改行コードの扱いについては、ファイルを読み込む際に呪文のように newline=''とするのが吉

Pythonスクリプト中からコマンド実行

コマンド実行させたい時って、どうするんだっけ?ってことで…

以下の2つの方法があるようですが、現在はあまり推奨されていないようです。

– os.system(command)
– commands.getoutput(command)

Pythonからコマンドを実行する – Qiita

ということで、利用するのは subprocess モジュールってことで公式ドキュメントを読むと、3.5, 3.6, 3.7あたりで仕様がチョコチョコとアップデートされているので実行環境がどのバージョンのPythonなのかは要注意

subprocess.run()

バージョン 3.5 で追加.

バージョン 3.6 で変更: encoding と error が引数に追加されました。

バージョン 3.7 で変更: Added the text parameter, as a more understandable alias of universal_newlines. Added the capture_output parameter.

subprocess — サブプロセス管理 — Python 3.10.0b2 ドキュメント

3.5よりも古いバージョンだと、subprocess.run()が使えないので、subprocess.call()subprocess.check_call()しないといけないとか

戻り値をテキストで受け取りには、encoding='utf-8'にするのは、3.6までで、3.7からはtext=Trueと書く方が適切とか

実際に発行するコマンドは、スペースで区切られた複合的なコマンドが多いので、shlex.split()使いましょうという話も重要

これで ls tmp を実行することができます。 このような場合、 shlex モジュールを用いて、コマンド文字列をリスト化できます。

Pythonでシェルコマンドを実行する – Mobile Factory Tech Blog

以下のようなコードが素敵コード

import shlex
import subprocess

cmd = 'ls tmp'
tokens = shlex.split(cmd) # => ['ls', 'tmp']
subprocess.run(tokens)

Pythonスクリプトに対する引数処理

argparse を使うとスマートに実装できるということで公式ドキュメント要チェック

argparse — コマンドラインオプション、引数、サブコマンドのパーサー — Python 3.10.0b2 ドキュメント

真偽のboolean型を扱い場合の注意事項とか、以下、よくまとまっている

【python】コマンドライン引数を扱うargparseを丁寧に – gotutiyan’s blog

コメント

タイトルとURLをコピーしました