Pythonノート: Pythonのモジュールやスクリプトについて

# 概要
Pythonでモジュールやスクリプトを書く場合のTips

# moduleについて

## module

再利用性の高いPythonスクリプトファイルを外部モジュールとして扱うことで、別のスクリプトから使うことができる。

__module定義例__
```py:ex_mod.py
def ex_hello():
    print("hello")
```

使用するモジュールはimport文でインポートする

```py
import ex_mod

ex_mod.
```


## `__name__` による動作の区別

```py
if __name__ == "__main__":
```
のような記述は何を意味しているか？  
pythonプログラムから外部モジュールとして呼ばれたか、記述されたファイル自身が実行スクリプトとして呼ばれたかの違いを区別している。

実行スクリプトとして呼ばれた場合は自動変数`__name__`に`__main__`が、モジュールとして呼ばれた場合はモジュール名が設定される。



### 記述例

pythonモジュールの例
```py
# module.py
def mod():
    print(f"name = {__name__}")

if __name__ == "__main__":
    mod()
```

単独のスクリプトとして実行すると
```bash:実行
$ ./module.py
```

```text:出力
name = __main__
```

以下のような外部の`main()`からモジュールとして呼び出す場合
```py
# main.py
import module

def main():
    module.mod()

if __name__ == "__main__":
    main()
```

main.pyを実行
```bash:実行
$ ./main.py
```

```text:出力
name = module
```


## importで参照するpath

importで参照する際のpathは`sys`モジュールの`sys.path`に格納されている

```py
import sys
import pprint as pp

pp.pprint(sys.path)
```

プリント結果
```
['/home/(current_path)',
 '/usr/lib/python38.zip',
 '/usr/lib/python3.8',
 '/usr/lib/python3.8/lib-dynload',
 '/home/g4p/work/pyt/venv/lib/python3.8/site-packages']
```


# コマンドライン引数

argparseモジュールを使用して処理するのが便利。

### まずはargparseをimportする

```py
# test_script.py
#!/bin/env python
import argparse
```

### ArgumentParser()メソッドでparserインスタンスを作る。
```py
parser = argparse.ArgumentParser(
    prog="test script",
    usage="./test_script.py [param] (options)",
    description="Description",
    add_help=True,
)
```

### 引数を追加する

- `add_arguments()`メソッドで引数を追加する。

#### オプション引数: optional arguments

- オプション引数は`'-n', '--name'`のように`'-'`接頭辞付きで指定する
```py
    parser.add_argument("-o", "--output", help="output file name")
```

- 値を受け取らないで単に動作のフラグとして使用したい場合、action指定する。
```py
    parser.add_argument("-v", "--verbose", help="verbose", action="store_true")
```

#### 位置引数: positional arguments

- 必ず値を取る必須な引数。`'-'`接頭辞なしで指定すると位置引数になる。
- 位置引数は指定が必須となる。
```py
    parser.add_argument("number")
```

### 値を参照する

parse_args()メソッドで値を参照することができる。
```py
args = parser.parse_args()
print(f"args = {args}")
print(f"number = {args.number}")
print(f"verbose = {args.verbose}")
```

```sh:実行
$ ./test_script.py -v 2 -o out.txt
```

```sh:出力
args = Namespace(number='2', output='out.txt', verbose=True)
number = 2
output = out.txt
verbose = True
```

### default値の指定

- default値の指定は`add_argument()`で`default='xxx'`と記載する。
```py
    parser.add_argument("-t", "--type", help="foramt type of output", default='txt')
    ・・・
    print(f"type = {args.type}")
```

```sh:実行
$ ./test_script.py -v 2 -o out.txt
```

```sh:出力
args = Namespace(number='2', output='out.txt', type='txt', verbose=True)
number = 2
output = out.txt
verbose = True
type = txt
```

# 標準ライブラリのモジュール

## 

## pprint による出力の整形

https://docs.python.org/ja/3/library/pprint.html

リストなど見やすく出力できる

```py
import sys
print(sys.path)
```

通常の`print()`での出力結果
```text
['', '/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', '/home/g4p/work/pyt/venv/lib/python3.8/site-packages']
```

`pprint`モジュールの`pprint()`を使う
```py
import sys
import pprint

pprint.pprint(sys.path)
```

`pprint.pprint()`での出力結果は適宜整形をしてくれる

```
['',
 '/usr/lib/python38.zip',
 '/usr/lib/python3.8',
 '/usr/lib/python3.8/lib-dynload',
 '/home/g4p/work/pyt/venv/lib/python3.8/site-packages']
```

#### プリント出力でなく文字列として取得したい場合
`pprint.pformat()`を使う

```py
str = pprint.pformat(sys.path)
print(str)
```

```
['',
 '/usr/lib/python310.zip',
 '/usr/lib/python3.10',
 '/usr/lib/python3.10/lib-dynload',
 '/usr/local/lib/python3.10/dist-packages',
 '/usr/lib/python3/dist-packages']
 ```

## 参考

https://maku77.github.io/p/o4m4jyg/