ウニ’s blog

勉強した結果を書いていきます

【Python3】requestsにthreadを使用すると非常に効果的

crawler,rest api等でrequestsにてgetを大量に投げる場合、ボトルネックになるのはI/Oバウンド。
入門Python3には以下の事が書いてる。

  • スレッドはI/Oバウンド問題の解決のために使う。
  • CPUバウンド問題では、プロセス、ネットワーキング、イベントを使う。

requests.get()している部分をworker threadとして切り離し、Queueにてタスクを管理するとかなり高速化できる。 計測結果とサンプルコードを記載する。

結果

requestsにて10回google検索結果を取得した結果。

タイプ 総実行時間(sec) response.elapsed合計値(sec)
thread 0.6119930744171143 0:00:01.050656
non thread 5.603970766067505 0:00:01.089367

9.3倍早く終る。素ん晴らしい!
総実行時間がresponse.elapsed合計値以下になってるのが感動する。

サンプルコード

non thread版

# non_thread.py

import datetime
import requests
import time

baseurl = "http://www.google.co.jp/search?hl=ja&q="

query_list = ['inu','neko','tori','sakana','kinoko','hebi','usagi','uma','hituzji','kabutomushi']
responses = []

start_time = time.time()

for q in query_list:
    responses.append(requests.get(baseurl+q))

elapsed_time = time.time() - start_time
print("total_time : {}".format(elapsed_time))

requests_time = datetime.timedelta()
for r in responses:
    requests_time += r.elapsed

print("requests_time : {}".format(requests_time))

thread版

# thread.py

import datetime
import queue
import threading

import requests
import time

def query_worker(query_queue):
    query = query_queue.get()
    responses.append(requests.get(baseurl + q))
    query_queue.task_done()

baseurl = "http://www.google.co.jp/search?hl=ja&q="

query_list = ['inu','neko','tori','sakana','kinoko','hebi','usagi','uma','hituzji','kabutomushi']
responses = []

# queueを設定
query_queue = queue.Queue()
for q in query_list:
    query_queue.put(q)

start_time = time.time()

# Thread start
while not query_queue.empty():
    w_thread = threading.Thread(target=query_worker, args=(query_queue,))
    w_thread.start()

# wait all thread are ended.
query_queue.join()

# total running time
elapsed_time = time.time() - start_time
print("total_time : {}".format(elapsed_time))

# http response total time
requests_time = datetime.timedelta()
for r in responses:
    requests_time += r.elapsed
print("requests_time : {}".format(requests_time))

参考

入門 Python 3

入門 Python 3

p330 11.1並行処理あたりを参考。
この本読みすぎてボロボロになってきた。

その他

PythonはGIL(グローバルインタープリタロック)が効いているのでCPUバウンド問題に対応するのにスレッド化は適さないので注意。逆に遅くなるよ!
あとはcrowlerを高速化しすぎてサーバーに怒られないように注意。

終わりに

高速化成功すると。気分いいですね。 並行処理、並列処理技術はめちゃめちゃ奥が深いので、まずは浅瀬で水浴びする程度から使っていきたい。
(おわり)

PythonでECサイトを作る(3)

コア処理修正。したけど、精度が落ちたので殆ど破棄。こういうこともある。
あとは相変わらず処理速度がくっそ遅い。なんとかしないと・・・。
対応策としては、プロセス分割すればいいのでは?とさっき思いついたので、明日ためそうと思う。

あとはサーバー構成検討し始めた。
GoogleCloudPratform使おうと思うけど、なんか入門する以前の状態で足踏みしてる感あり。正月ボケかなあ。
あまりCloud全般の知識がない感じだが、とりあえずHeroku的なPasSで良いと思うので、GoogleAppEngineを試してみよう。
(おわり)

loggerを使う(3)--完了

logging.confの[loggers]の名称にアンダーバーを使ってたら上手くいかなかったようだ。
名称を変えたらうまく行った。

あとは、log levelがError以上だったらslackに送るようにした。
slack連携はハマらず素直に動くのでいつも感動する。

なんでもかんでもSlackに入れてる人どうなん?と思ってたけど、ちょっと気持ちがわかってきた。

参考

inokara.hateblo.jp

終わりに

最近気づいたけど、Desktop版Slackめちゃめちゃメモリ使うのね…。いいけど。

loggerを使う(2)

公式のHowToをまぁまぁ読んだ。全てのprint文の置き換えと、config化した。
システムのconfigと、bs4用configとlogger用configがあり、projectのRoot Directoryがごちゃごちゃしてきたので整理した。
f:id:uni8inu:20161228033133p:plain

…今度はDirectoryが多い…。

参考

公式

Logging HOWTO — Python 3.5.2 ドキュメント

config化参考

takemikami.com

課題

logging.confファイルの設定がいまいち効いてないような?
表示レベルをDebugに設定しているのにInfoレベルまで表示されている。

サブモジュール内のloggerが上手く行ってるのかデバッグする必要あり。

loggerを使う(1)

print文仕込みマンだったけど、コードの規模が大きくなってきた。
loggerを使っていこう。

と思って調べたら、怒れる人が居て怖い。

怒れる記事

qiita.com

知識0でこの記事をよんでも何に怒りを感じているか全然わからなかった。

参考

簡単な概念。

st-president-program.seesaa.net
ログレベルとフィルター。出力先の操作ができる。

簡単な使い方。

Python loggingモジュールの基本的な使い方 - Symfoware
簡単。

公式の丁寧なHOWTO

Logging HOWTO — Python 3.5.2 ドキュメント
今は流し読み。
(2)の記事で頑張ろう。

ルートロガーを使用すると他人のロガーに影響あり

media.accel-brain.com

ここまで読んで、ようやく冒頭の記事の怒りの内容がわかってきた。
基本作法としてgetLoger(__name__)を忘れなければ良さそう。

実践する

入門30分なので、高度にloggerを使いこなせそうにない。
とりあえず、標準出力、ファイル出力、ログレベル設定を気にしながらソースに仕込んでいこう。

さてさて、logger設定をconfigと連携させる必要あるかな?…あるなー。
面倒だが、やろう。

BeautifulSoup4で全ての文字を書き換える

タグを辿って、tag.stringの書き換えを繰り返すと、NavigableStringは書き換え不可能!と怒られた。ごめん。
公式documentをよく読んだら、replace_with()つかえとのこと。
teratailに質問もいいけど、公式ドキュメントも読もう。うん。

参考

BeautifulSoup公式
Beautiful Soup Documentation — Beautiful Soup 4.4.0 documentation

実装例

BeautifulSoup4 TreeNode traverse and fix Navigable ...

その他

blogをはてな記法で書いてたけど、markdownに慣れるためにmarkdownモードにした。
慣れたいな~。