pythonメモ

準備

コード規約

pipインストール参考

pyenv

必要なライブラリインストール
$ sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils


pyenvのインストール
$ git clone https://github.com/yyuu/pyenv.git ~/.pyenv


$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(pyenv init -)"' >> ~/.bashrc


パスの再読込
exec $SHELL

pyenvの確認

$ pyenv install -l
Available versions:
  2.1.3
  2.2.3
  2.3.7
  2.4
  2.4.1
  2.4.2
多いので省略
  • 3.5.4をインストール
$ pyenv install 3.5.4
Downloading Python-3.5.4.tar.xz...
-> https://www.python.org/ftp/python/3.5.4/Python-3.5.4.tar.xz
Installing Python-3.5.4...
                                                                                                                           Installed Python-3.5.4 to /home/ユーザ名/.pyenv/versions/3.5.4                                                                                        
  • バージョン確認
$ pyenv versions
* system (set by /home/ユーザ名/.pyenv/version)                                                                                
  3.5.4
  • バージョン切り替え
$ pyenv shell 3.5.4
$ pyenv versions
  system    [                                                                                           
* 3.5.4 (set by PYENV_VERSION environment variable)

pyenv local 3.5.4で環境を切り替えても、その上のディレクトリには適用されていないようだった(要確認)

  • pyenv環境の削除
 $ pyenv uninstall 3.5.4
pyenv: remove /home/ludwig125/.pyenv/versions/3.5.4? yes
$ 

環境変数

os.getenv

os.getenv(varname[, value])

  • 環境変数 varname が存在する場合にはその値を返し、存在しない場合には value を返す

os.environ

例
「host101, host201, host301, host401」
「host_role」というkeyのroleに上記のサーバを登録した場合、roleに登録されたサーバの確認方法は以下のようにする
for role in env.roledefs.keys():
    print env.roledefs[role]

→実行結果
['host101', 'host201', 'host301', 'host401']

文法

リスト(配列)

data = []
for i in range(1, 6):
    data.append(i * 2)

print data

リスト内包表記

data2 = [i * 2 for i in range(1, 6)] print data2

map

mapは配列の各要素に対して関数を実行する

以下はmap(関数, 配列)

data3 = map(lambda x : x*2, range(1, 6))
print data3

実行結果

$ python list.py
[2, 4, 6, 8, 10]
[2, 4, 6, 8, 10]
[2, 4, 6, 8, 10]

リスト内包表記

  • 10以下の奇数を作成する
    • リスト内包表記 のあとにif文でフィルタリングできる
>>> [ i for i in range(1, 11) if((i % 2) == 1)]
[1, 3, 5, 7, 9]

python デコレータ

デコレータ例

  • 関数が実行にかかった時間を表示するデコレータ
import time                                                                                     


def time_log(func):
    def wrapper(*args, **kwargs):
        print("start: " + func.__name__)
        start_time = time.time()
        res = func(*args, **kwargs)
        end_time = time.time()
        print("end: " + func.__name__ , " elapsed time:" + str(end_time - start_time))
        return res
    return wrapper

@time_log
def func1():
    print("Boys, be ambitious")
    time.sleep(3)
    print("Girls, be ambitious")

func1()

実行結果

$ python deco_time.py 
start: func1
Boys, be ambitious
Girls, be ambitious
('end: func1', ' elapsed time:3.00378608704')

serial

どんなタスクも serial を指定すると設定を無視してシリアルで実行します。 http://fabric-ja.readthedocs.org/ja/latest/usage/parallel.html

roles

正規表現

match

文字列のエスケープとmatch - http://python-doc-ja.readthedocs.org/en/latest/howto/regex.html

ホスト名からホスト番号を取り出す

例:
ホスト名:host022101.co.jp
→ 022101を取り出す
host = "adsearch022101.co.jp"
pattern = r"([a-z]*)(\d*)"
m = re.match(pattern, host)
host_num = m.group(2)
print host_num
 
⇒ 022101

辞書

Tips

一つの長い行を途中で折り返す
方法1.バックスラッシュ「\」を使う
test = '%s \
         %s' % ("aaa", "bbb")
 
ただしこれだと 折り返した後の行頭からの空白が出力されてしまう
>>> test = '%s \
...          %s' % ("aaa", "bbb")
>>> print test
aaa          bbb
方法2.括弧で囲う
test2 = ('%s '
         '%s' % ("aaa", "bbb"))
 
これなら余計なスペースは入らない
>>> test2 = ('%s '
...          '%s' % ("aaa", "bbb"))
>>> print test2
aaa bbb
 
 
これでも大丈夫
test2 = ('%s '
         '%s' 
         % ("aaa", "bbb"))

>>> test2 = ('%s '
...          '%s'
...          % ("aaa", "bbb"))
>>> print test2
aaa bbb

GUI

参考:実践力を身につける Pythonの教科書 | マイナビブックス

Tkinter

import tkinter.messagebox as mb

ans = mb.askyesno("question", "Do you like nooble")

実行

$ python3 dialog.py

最初失敗

$ python3 dialog.py
Traceback (most recent call last):
  File "dialog.py", line 1, in <module>
    import tkinter.mesagebox as mb
  File "/usr/local/lib/python3.6/tkinter/__init__.py", line 36, in <module>
    import _tkinter # If this fails your Python may not be configured for Tk
ModuleNotFoundError: No module named '_tkinter'
$ sudo apt install python-tk tk-dev
$ pyenv install 3.5.1

再度実行

$ python3 dialog.py

f:id:ludwig125:20171021230910p:plain

あとでまたできなくなったので、改めて確認

ludwig125.hatenablog.com

Webサーバを立てる

参考:実践力を身につける Pythonの教科書 | マイナビブックス

pythonでWebサーバを起動

8181ポートでWebサーバを起動してみる

python3 -m http.server --cgi 8181

詳細はこちらに記載

ludwig125.hatenablog.com

Webサーバとして、URLのパラメータの値を取得する

参考:実践力を身につける Pythonの教科書 | マイナビブックス

chap5/5-2/cgi-bin] $ cat show-params.py 
#!/usr/bin/env python3

import cgi

# header
print("Content-Type: text/html; charset=utf=8")

print("")

print("<pre>")
# URLパラメータを取得する
form = cgi.FieldStorage()

# 特定のパラメータを取得して表示
mode = form.getvalue("mode", default="")
print("mode=", mode)

# すべてのパラメータを取得して表示
print("--- all params ---")
for k in form.keys():
    print(k, "=", form.getvalue(k))                       

cgi-binより上のパスでWebサーバ起動

chap5/5-2] $ python3 -m http.server --cgi 8181
Serving HTTP on 0.0.0.0 port 8181 (http://0.0.0.0:8181/) ...
192.168.3.2 - - [31/Oct/2017 23:51:32] "GET /cgi-bin/show-params.py?mode=test&n=30&q=500 HTTP/1.1" 200 -

f:id:ludwig125:20171101000253p:plain

インスタンス

クラスのオーバーロード

class Pos:

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other):
        x2 = self.x + other.x
        y2 = self.y + other.y
        return Pos(x2, y2)

    def add(self, other):
        # オーバーロードではなく関数呼び出しで同じ結果を得ることができるか・・?
        x2 = self.x + other.x
        y2 = self.y + other.y
        return Pos(x2, y2)

    def __str__(self):
        return "{0}, {1}".format(self.x, self.y)


p1 = Pos(10, 20)
p2 = Pos(100, 400)

p3 = p1 + p2 # +演算子をオーバーロードした__add__を使う
print(p3)

p3 = p1.add(p2) # 上記のp1 + p2 はこれと同じこと
print(p3)

結果

$ python3 pos-add2.py
110, 420
110, 420

テスト

unittest

pytest

  • 参考:Python testing 勉強会(1) pytestを使ってみる
インストール
flake8入れる
flake8
sudo easy_install-2.7 flake8
pip入れる
pip
sudo easy_install-2.7 pip
pytest入れる
sudo pip install pytest

pytest実行

-v

pytestに「-v」を付けると差分が詳細表示される --caputure=no --caputure=no でテスト中のprint文などを出力する

monkeypatch

http://thinkami.hatenablog.com/entry/2017/03/07/065903 https://docs.pytest.org/en/latest/monkeypatch.html http://niwaringo.tumblr.com/post/66948561978/pytest%E3%81%AEmonkeypatch%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6urllibrequest%E3%81%AE%E3%83%A6%E3%83%8B%E3%83%83%E3%83%88%E3%83%86%E3%82%B9%E3%83%88%E3%82%92%E3%81%99%E3%82%8B

トラブル対応

ludwig125.hatenablog.com