ちょっとしたスクリプトなんだけど一般的な御作法とかスッカリ忘れてしまったので、コアな処理部分だけじゃなくて、前後のお決まりコードなども含めて、思い出しがてら書き残しておく
スクリプト作成時に知っておくべきこと
冒頭に書いたお作法的なことを知らないで書いているのって… なんか… ダサいじゃん?w
よくあるのが、即興でパターン1で書き、書き換えているうちにパターン2,3となり、他のスクリプトからも利用したくなりパターン4に改良した、というケースです。
(snip)
Pythonファイルは、必ず
__name__
という属性を持ちます。そのファイルがプログラムとして起動されると'__main__'
が値として代入されます。つまり、__name__ == '__main__'
が成立する時は、プログラムとして起動しているので、main()
を実行します。(snip)
スクリプトはその場限りで作成することもよくあるので、パターン1や2を採用することが多いかもしれませんが、最終的には「パターン4」を用いることをお勧めします。
Pythonスクリプトの書き方(4パターン) – ガンマソフト株式会社
パターン1-4ってなんだ?って話だけど、その詳細はリンク先を見てもらうとして
- パターン1:逐次型 … ベタ書き
- パターン2:関数+実行文 … まとまりのある処理を関数化
- パターン3:main()関数 … スコープ意識して開始部分も関数化
- パターン4:インポート時の実行回避あり … 再利用を意識した作り
以下のあたりも「なぜ?」の答えなので色々実装してみて経験から腹落ちできているといいよね
Python では本来
main
関数を定義する必要はありませんが、経験者が書いたスクリプトではよくmain
関数が書かれています。 筆者は Python を学び始めた頃にそのようなコードを見て「必要ないものをなぜわざわざ書くのだろう?」と疑問に思いました。 今回は筆者自身がかつて抱いたこの疑問に答えてみます。尚、
main
という名前を使うのはただの慣習です。 この名前の関数にしないといけない制約は特にありません。1. 関数の定義を後ろに書ける
Python Tips: Python で main 関数を定義することのメリット – Life with Python
2. 抽象度の高い処理の流れをmain
関数で示せる
3. 処理の変更や差し替えがしやすい
4. テストが書きやすい
5. 変数名の意図しない衝突を防げる
__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なんかも抑えておきたところ…
- PEP 8 — Style Guide for Python Code | Python.org
- styleguide | Style guides for Google-originated open-source projects
- 【Pythonコーディング規約】PEP 8 vs Google Style – Qiita
- VS Code コーディング規約を快適に守る – Qiita
以下は、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(
Pythonからコマンドを実行する – Qiitacommand
)
– commands.getoutput(command
)
ということで、利用するのは 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()
使いましょうという話も重要
これで
Pythonでシェルコマンドを実行する – Mobile Factory Tech Blogls tmp
を実行することができます。 このような場合、shlex
モジュールを用いて、コマンド文字列をリスト化できます。
以下のようなコードが素敵コード
import shlex
import subprocess
cmd = 'ls tmp'
tokens = shlex.split(cmd) # => ['ls', 'tmp']
subprocess.run(tokens)
Pythonスクリプトに対する引数処理
argparse
を使うとスマートに実装できるということで公式ドキュメント要チェック
argparse — コマンドラインオプション、引数、サブコマンドのパーサー — Python 3.10.0b2 ドキュメント
真偽のboolean型を扱い場合の注意事項とか、以下、よくまとまっている
コメント