sysの使い方 【Python3】

今回はカレンダーを出力するプログラムを作成時`Python`の`built-in module`である`sys`を使用する機会があったので、使い方を記事にまとめていきたいと思います。

## sysモジュールとは？

Pythonの標準ライブラリ（built-in module）のひとつで、**インタプリタや実行環境に関する情報や操作**を行うための便利なツールです。

### 主な用途
- コマンドライン引数の取得（`sys.argv`）
- 実行中のOSやプラットフォーム情報の取得（`sys.platform`）
- プログラムの強制終了（`sys.exit()`）
- モジュール検索パスの取得・変更（`sys.path`）

---
私自身未経験者でこの用語って何を指しているんだったっけとなることが、あったので初学者の方向けにも用語の説明を入れていきたいと思います。

## インタプリタとは？

プログラミング言語で書かれたコードを、**逐次的に読み解き、実行していくソフトウェア**です。
Pythonはインタプリタ型言語で、**1文ずつ読み取りながら即座に実行**されます。

---

## スクリプトの起動パラメータとは？

スクリプト（例：`example.py`）を実行する際に、コマンドラインで追加できる情報のことです。

```bash
$ python example.py arg1 arg2
```
このとき、sys.argv に格納される内容は：

```python
['example.py', 'arg1', 'arg2']
```
このように、引数は半角スペースごとに分割され、リスト（[]）として格納されます。
これを使えば、コマンドから入力された値をプログラム内で処理できます。

上記の内容と重複する部分もありますが、今回カレンダーを出力するプログラムを作成した際に使用したメソッドを備忘録も兼ねて書いていきます。

以下が出力例になります。

[![Image from Gyazo](https://i.gyazo.com/6a9e3d6f5f54c735becba3fef6ace58a.png)](https://gyazo.com/6a9e3d6f5f54c735becba3fef6ace58a)

---
## カレンダーを出力するプログラム作成で使用したメソッド

### `args = sys.argv`

`sys.argv` はコマンドライン引数をリスト形式で取得するためのプロパティです。  
このリストの最初の要素（sys.argv[0]）はスクリプト自体の名前で、それ以降に続く要素が実際の引数になります。

以下はコード例になります。
コマンドラインからスクリプト実行時にスクリプト名のみならプログラム実行日時に該当する月、引数ありの時は該当する月のカレンダーを出力させるために引数の判定を行うための関数になります。
```diff_python
import sys

def argument_judgement():
+    args = sys.argv                       # このソースコード
    if len(args) == 1:
        today = datetime.date.today()
        return today.year, today.month
    if len(args) == 3 and args[1] == '-m':
        today = datetime.date.today()
        year = today.year
        month = check_the_month(args[2])
        return year, month
    print(f"{args} is neither a month number (1..12) nor a name")
    sys.exit(1)
```


```bash
$ python example.py -m 12
```
と実行した場合、`args`に格納される内容は以下の通りです。

```bash
['example.py', '-m', '12']
```

このように、外部から指定された値をプログラム内で柔軟に使うことができます。
格納されている値は全て文字列型になっているので、注意しましょう。

### `sys.exit()`

`sys.exit()` は、プログラムを任意のタイミングで終了させたいときに使用します。  
特に、想定外の引数が与えられたときにエラーを表示して処理を強制終了したい場合などに役立ちます。

```diff_python
def argument_judgement():
    args = sys.argv
    if len(args) == 1:
        today = datetime.date.today()
        return today.year, today.month
    if len(args) == 3 and args[1] == '-m':
        today = datetime.date.today()
        year = today.year
        month = check_the_month(args[2])
        return year, month
    print(f"{args} is neither a month number (1..12) nor a name")
+    sys.exit(1)   # ここのソースコード
```
exit に渡す数値（ここでは 1）は終了ステータスと呼ばれ、0は正常終了、1以上はエラー終了を意味します。

そのほかのメソッドは下記公式ドキュメントを確認してみてください。
https://docs.python.org/ja/3/library/sys.html

---

### VSCodeで実行とデバッグの機能を複数の引数を設定して進める方法

VSCodeでは、デバッグ時にコマンドライン引数を渡すことができます。  
手順は以下の通りです。

1. 左側の「実行とデバッグ」アイコンをクリック
[![Image from Gyazo](https://i.gyazo.com/f57709a4e33759f0de4f1a3cee97723a.png)](https://gyazo.com/f57709a4e33759f0de4f1a3cee97723a)
2. launch.json ファイルを作成（または編集）  
3. 次のように args を追加

```launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Python: 現在のファイル",
      "type": "python",
      "request": "launch",
      "program": "${file}",
      "console": "integratedTerminal",
      "args": ["-m", "3"]
    }
  ]
}
```

上記では、スクリプトを  
python example.py -m 3
のように引数付きで実行するのと同じ意味になります。  
これにより、実際のコマンドラインと同様の動作をVSCode上で再現できます。

https://qiita.com/KororonX/items/969e934bf762e53760cc

上記記事にあるように実行とデバッグを行うごとに自身で引数を入力して行う方法もあるみたいですが、うまくいかなかったので実行時の引数を変更したい場合は面倒ですが、先ほど紹介させていただいたやり方で都度変更してデバッグを行いました。

---

## argparseの紹介（sysとの違い）

今回は sys.argv を使ってコマンドライン引数を処理しましたが、Pythonには argparse というより柔軟で強力なライブラリも用意されています。
sysとの違いを把握してより理解できると思ったのでここで紹介させていただきます。

argparse の主なメリットは以下の通りです。

- 引数の自動解析（型変換や存在チェックなど）  
- ヘルプメッセージの自動生成（-h で使い方を表示）  
- オプション引数（例: --month 3）などの記述もサポート  

以下は argparse を使った簡単な例です。

```python
import argparse

parser = argparse.ArgumentParser()  
parser.add_argument("-m", "--month", type=int, help="表示する月を指定")  
args = parser.parse_args()

print(args.month)
```

このコードは、
```bash
$ python script.py -m 3
```
や  
```bash
$ python script.py --month 3 
```
のような形で実行でき、入力された月の値を受け取れます。

初学者には sys.argv の方がシンプルでわかりやすい一方で、複雑な引数処理が必要な場面では argparse が非常に便利です。

<dl>
    <dt>sys.argv : 
    <dd>軽量、自力でなんでもできる。自由だけど複雑な引数処理が必要な場面は面倒
    <dt>argparse : 
    <dd>ちょっと重いけど、多機能で安全
</dl>

頭の片隅に入れておいて将来的に活用できればと思います。

## 終わりに

今回は、カレンダーを出力するプログラム作成を通じて sys モジュールの基本的な使い方や、コマンドライン引数の扱いについて学びました。

引数の扱いは型をきちんと理解して取り扱っていきたいと思います。

また、VSCodeを使えば複数の引数を指定して簡単にデバッグできるため、開発効率も上がります。  
さらに発展的な使い方として argparse も覚えておくと、よりユーザーフレンドリーなスクリプトを作れるようになります。

今後も一歩ずつ、理解を深めながらステップアップしていきたいと思います。

> 参照
>> sys --- システム固有のパラメーターと関数 : 
https://docs.python.org/ja/3/library/sys.html

> 参考記事
>> VSCodeのPythonデバッガー構成で実行時に指定する引数が連結されてしまうことについて : 
https://qiita.com/KororonX/items/969e934bf762e53760cc