Pythonでよく使うけどすぐに忘れてしまう関数やメソッド

# 個人的備忘録
Pythonでよく使うけどすぐに忘れてしまうコマンドなのを書き留めておく。
なんですぐに忘れてしまうん？

## ファイル読み書き
>https://note.nkmk.me/python-file-io-open-with/

↑良記事！

### numpyで書き込み

```text.py
import numpy as np
np.savetxt("foo.txt", numpy_array_to_write, delimiter=",")

```

### with openで書き込み

```text.py
with open("hello.txt", "w") as f: 
    f.write("Hello World") 
```

### with openで読み込み

```read.py
file = open("hello.text", "r") 
print(file.read())
```

"rb","wb"との差がよくわかってない(py3.5)。
>https://stackoverflow.com/questions/33054527/python-3-5-typeerror-a-bytes-like-object-is-required-not-str-when-writing-t

## ファイル取得関連

### globを使ってdirectoryのファイルをすべて取得
多数のファイル操作をする時に必須。
globが個人的には一番便利。

```python

# ls /home/hoge
# 1.jpg 2.jpg

import glob

files = glob.glob('/home/hoge/*.jpg')

# files = [/home/hoge/1.jpg, /home/hoge/2.jpg]

# またsortedを使えば昇順にlistが並ぶため便利。
files = sorted(glob.glob('/home/hoge/*.jpg'))

```

### ファイル名取得(os.path)
os.pathを使うと様々なファイル名、ディレクトリ名取得が可能。
https://note.nkmk.me/python-os-basename-dirname-split-splitext/

```py
# /home/dir/text.txt
#     text2.txt
#があるとする。

import glob
import os

directory = "/home/dir/"

# フルパスを取得
files = glob.glob(directory+"*") # ワイルドカードを入れる
print(files)
# /home/dir/text.txt
# /home/dir/text2.txt

# ファイル名のみ取得
print(os.path.basename(directory))
# text.txt
# text2.txt

# dir名のみ取得
print(os.path.dirname(directory))
# dir

# dirとファイル名を同時に取得
print(os.path.split(directory))
# /home/dir, text.txt
# /home/dir, text2.txt
```

### ファイルの存在の確認(os.path.isfile, os.path.isdir)
os.path.isfile(path/to/file)の出力はbool.
指定ファイルが存在するならばTrueを返す.

```py
# dir/text.txt
#     text2.txt
# があるとする。
import os 

print(os.path.isfile("dir/text.txt"))
# True

# os.path.isdirはディレクトリが存在するか調べる
print(os.path.isdir("dir"))
# True
print(os.path.isdir("hogehoge"))
# False
```

## Parser関連
### Parser基本
``` parser.py
import argparse

# parserの記述
parser = argparse.ArgumentParser()
parser.add_argument("-n", dest="num_bit", default=32)
args = parser.parse_args()

# 呼び出す場合
num_bit = args.num_bit

# rest of the code..

```

```reidai.sh
python parser.py -n 16
```

のように使う。非宣言時はdefaultが入る。
pythonをスクリプト的に使う場合必須。

### Parserちょっと応用
必要なデータが宣言されてない時にエラーを出すようにもできる。(path)
また宣言されたときのみにTrueを返すaction='store_true'なども書ける。(cuda)

```parser2.py
parser = OptionParser()
parser.add_option("-p", dest="test_path", help="path to test data.")
# cuda: default is False
parser.add_option('--cuda', dest='cuda', help='whether use CUDA', action='store_true')
(options, args) = parser.parse_args()

if not options.test_path:   # if filename is not given
	parser.error('Error: path to test data must be specified. Pass --path to command line')

# rest of the code..

```

### shellを作る。
shellを作っておけば複数のテストをシーケンシャルに流せて便利。
帰って明日出社するときまでにsimを沢山回したい時に。。
このスクリプトのデバッグを怠り翌日何も回ってないのは誰もが経験する話

$bash job.sh
などで流しておく。

```job.sh
python parser.py -n 32
python parser.py -n 16
python parser.py -n 8
python parser.py -n 4
#....
```

## ループ関連

### for
zipとenumerateを忘れがち。

```for.py
a = range(3)
b = range(10,13)

for i in a:
 print(i)

# returns i and ii
for (i,ii) in enumerate(b):
 print("i:",i)
 print("ii:",ii)

# a is returned to i, b is returned to ii respectively
for (i, ii) in zip(a,b):
 print("i:",i)
 print("ii:",ii)
 
```

出力：
0
1
2

i: 0
ii: 10
i: 1
ii: 11
i: 2
ii: 12

i: 0
ii: 10
i: 1
ii: 11
i: 2
ii: 12

## よく使うけど忘れる配列操作


```py

a = [0,1,2,3,4,5,6,7,8,9]

# 最後の要素のみ抜き取る
# foo[-n] で後ろからn番目の要素を取得
print(a[-1])
# 9

# 1こ飛ばしに抜き取る (or 偶数要素を取得）
# # foo[::n] でnのslicing
print(a[::2])
# [0, 2, 4, 6, 8]

# 奇数番目を取得する
# 要素[1]から一つ飛ばしに取得
print(a[1::2])
# [1, 3, 5, 7, 9]

# 配列を逆転
print(a[::-1])
# [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
```

## Pythonスクリプト内でshellコマンドを実行
> 
Python Execute Unix / Linux Command Examples
https://www.cyberciti.biz/faq/python-execute-unix-linux-command-examples/

subprocessでlinuxコマンドを実行可能。
これにより結果を保存するディレクトリを作ったり不要なファイルを削除したりできる。
os.sysも同様のことができるがバグが多いとのこと。

```py

# example
import subprocess
subprocess.call("command")

# mkdir
subprocess.call("mkdir foo")
# ファイルをfooディレクトリに書き込み
with open("foo/hello.txt", "w") as f: 
    f.write("Hello World") 

# remove files
subprocess.call("rm hoge*")

#エラーが出たときはshell=Trueを追加すると上手くいくことが多い
subprocess.call("rm hoge*", shell=True)
```

## コマンドラインからPythonを実行
python -c 'hoge'でPythonスクリプトを実行可能。
例えばpipやcondaでいろいろインストールをしていてちゃんとcaffeやpytorchが入ったか確認する時に便利。

```
python -c 'import caffe'
```