ludwig125のブログ

頑張りすぎずに頑張る父

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

vimメモ

vimrcメモ

.vimrcの設定メモ - ludwig125のブログ

vim参考

http://uguisu.skr.jp/Windows/vi.html

現在の設定を出力する — 名無しのvim使い

自分のメモ

ビジュアル矩形モード

  • ubuntuのterminalを使っていて、ビジュアル矩形モードがCtrl+vでできないので悩んでいたけど、Ctrl+Shift+vに割り当てられていた
  • Terminalの設定でペーストを デフォルトのCtrl+Shift+vからCtrl+v に変えたことが関係しているんっだろうか。。? とりあえずこれでやって今度調べようかな

UbuntuのTerminalのショートカットキーを変更する

環境

Ubuntu 14.04

やりたいこと

UbuntuのTerminalデフォルトのショートカットキーでは

コピー:Shift+Ctrl+c

ペースト:Shift+Ctrl+v

となっているので、使いやすいように変える

 

変えるところ

Terminalの「編集」→「キーボードショートカット」を開く

Ctrl+cをコピーにしてしまうとプロセスを中断できなくなってしまうので、

使っていない「caps lock」を代わりに使うことも考えたが、結局わかりやすい「Ctrl」を使うことにした

f:id:ludwig125:20171006224627p:plain

 

Ubuntuの環境にpythonをインストールする

以下のURLからdownload

https://www.python.org/downloads/

そのあと以下の手順でインストール

Linuxに好きなバージョンのPythonをインストールする方法 - AkicanBlog

ls
$ cd (解凍したPythonのフォルダ名)
sudo ./configure
sudo make
sudo make install

以下のようなエラーが出たので-Hを使う

The directory '/home/shingo/.cache/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
The directory '/home/shingo/.cache/pip' or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
Requirement already up-to-date: setuptools in /usr/local/lib/python3.6/site-packages
Requirement already up-to-date: pip in /usr/local/lib/python3.6/site-packages

できたみたい 

$ which python3
/usr/local/bin/python3

なぜか2.7しか認識されていない

$ python --version
Python 2.7.6 

 ただ、python3のパスはとっている

$ which python3
/usr/local/bin/python3

 

Android 6.0.xで「画面オーバーレイを検出」と出て解決できない

色々検索してもブルーライトフィルターを使っている場合しか出ないので困っていた。

自分の場合、Biscuitという英単語帳を常駐させていたためできなかった。

はあ。こんなのに時間取られた

検索についていろいろウェブから拾ってきてまとめたメモ

検索についていろいろウェブから拾ってきてまとめたメモ

転置索引において,単語と文書の対応付けの情報をポスティング(またはポインタ)と呼びます。
各単語におけるポスティングの列のことをポスティングリストと呼びます。


http://gihyo.jp/dev/serial/01/search-engine/0004
転置索引は大きく分けて2つの部分から構成されています。
文書に出現する単語のリストである「辞書」と,
その辞書にある各単語がどの文書に出現するかを表したポスティングリストの集合の「転置リスト」からなります(図1)。


辞書は単語だけでなく,その単語に対応するポスティングリストの位置情報を含んでいます。
よって,辞書を探索することで,該当する単語のポスティングリストを取り出すことが可能となります。


ブーリアン検索
論理演算子ブーリアンオペレータ)のAND,OR,NOTを使って適合する文書を探し出す

検索エンジンでは,ブーリアン検索により検索を行い,
その結果を何らかの基準(スコア,日付など)で並び換え,その結果をユーザに提示することが多い

 

文書に単語が出現したか否かという情報
⇒ 文書レベルのポスティングリスト(Document-level inverted list)

 

文書レベルの情報に加えて,
単語が文書中のどこに出現するか(先頭から何単語目か)という情報を含んだポスティングリスト
⇒ 単語レベルのポスティングリスト(Word-level inverted list)といい,
各ポスティングをDocID:offset1,offset2... のように表現します。


フレーズ検索
単語レベルの転置リストを使うことで,"search engine" というフレーズが検索可能となります。
"search"と"engine"が隣り合って出現しているかをチェックすることによりフレーズの存在の有無を確認します。

 

http://gihyo.jp/dev/serial/01/search-engine/0005
B+木
B+木はB木から派生したデータ構造
全てのレコードは木の葉ノード(leaf node)に格納され,
内部ノード(internal node)にはキーのみが格納される木構造

B+木は,各ノードをページと呼ばれる単位で管理し,
通常はそれをファイルシステムのブロックサイズの定数倍にします。

大規模な辞書をブロックデバイス上で扱う場合は,B+木を利用することで効率的に管理することができます。


http://gihyo.jp/dev/serial/01/search-engine/0005?page=2
転置リストは,各単語におけるポスティングリストの集まり
これらは通常辞書とは別の領域(ファイル)に保存されます。
各リストは隣りあって格納され,辞書がそのリストへの(オフセットなどの)位置情報を保持しているという構造

辞書:メモリ or ディスク上
ポスティングリスト:ディスク上


ポスティングリストの圧縮

転置リストを構成する各ポスティングリストは,検索したい文書数が増えるほど長くなります。
よって,中規模以上の文書におけるポスティングリストでは,
その取得におけるディスクI/Oが検索処理において非常に大きな比重を占めてしまいます。
この問題に対処するために,通常ポスティングリストは圧縮して格納され,ディスクI/Oの削減を図ります。

ポスティングリストは整数列となるため,整数列に向いた圧縮手法が用いられます。

 


http://gihyo.jp/dev/serial/01/search-engine/0006
文を単語や文字の並びに分割する方法

日本語のように単語が空白で区切られていない文を単語に分割するには,大きく分けて以下の2つの方法があります

1.形態素解析による分割
2.N-gram(q-gram)による分割


1.形態素解析による分割
形態素解析(Morphological Analysis)とは,
文を言語で意味を持つ最小単位の"形態素"の列に分割し,それぞれの品詞を判別すること

2.N-gram(q-gram)よる分割
N-gramとは文字のN文字の部分列のことを指し,Nには2や3などの数値が入ります
N-gramによる分割とは,文を単語の境界とは関係なくN文字ずつに分割することを言います。
全文検索エンジン」を2-gram(bi-gram)で分割した場合は,
「全文」「文検」「検索」「索エ」「エン」「ンジ」「ジン」となります。

 

形態素解析による転置索引の利点と欠点

利点は,文に対して辞書に登録するターム数が少なくなることから,
N-gramに比べて辞書,転置リストのサイズが小さくなり,また構築処理,検索処理も速くなります。

欠点は,検索漏れが生じてしまうことになります。
検索漏れとは,実際にクエリが文に含まれているにもかかわらず,見つけられないことを言います。


N-gramによる転置索引の利点と欠点
利点は,形態素解析の場合と異なり,検索漏れが発生しないことです。
これは,N-gramではすべての文字部分列をタームとして登録するため,
検索キーワードが文章に含まれていれば必ず見つけることができます。

欠点としては,上記のことから,辞書のサイズ,転置リストのサイズが大きくなってしまい,
構築処理・検索処理が形態素解析の場合と比べて少しだけ遅くなってしまいます。


日本語文書における転置索引の実装
現代の検索エンジンは,文の分割方法に依存しないように設計されることが多い

 

 


http://gihyo.jp/dev/serial/01/search-engine/0007
ディスクベースの構築方法

多くの場合,転置索引は実メモリよりも大きくなります

ディスクベースの構築方法
今回はSort-based InversionとMerge-based Inversionと呼ばれる2つの方法


■構築方法の種類
転置索引の構築には,大きく分けて以下の2種類の構築方法があります。

静的な構築方法(offline index construction, offline approarch)
動的な構築方法(online index construction, online approarch)


Web上のニュースやブログなどの場合,新しい記事は古い記事よりも重要度が高い
そのような場合には動的な構築方法が選ばれます。

 


http://gihyo.jp/dev/serial/01/search-engine/0008
検索の流れ

1.転置索引における一般的な検索処理の流れは,以下のようになります。
2.クエリ中の各タームのポスティングリストを取得
3.ブーリアン(Boolean)検索によりマッチした文書IDの取得
4.マッチした各文書とクエリの適合度計算またはソート属性値の取得
5.適合度 または 属性値により並び換え
6.上位k件(通常10件~100件)を返す


関連度によるランキング
文検索では,関連度を計算して並び変える場合が多くあります

代表的な関連度指標には,コサイン類似度(cosine similarity)やOkapi BM25などがあります。

 

.vimrcの設定メモ

.vimrc

https://github.com/ludwig125/work/blob/master/dotfiles/.vimrc

Neobundleをインストール

NeoBundleを用いたVimプラグイン管理と色設定メモ - Qiita

 

[~ ] $ mkdir -p ~/.vim/bundle
[~ ] $ git clone git://github.com/Shougo/neobundle.vim