2015年12月26日

lazy import 2

lazy import の更なるテクニックを紹介します。


こちらで lazy import を紹介しました。lazy import の実装例を再掲します。

def cat(filename):
    if filename.startswith('http://'):
        import urllib.request  # ここでimport
        print(urllib.request.urlopen(filename).read())
    else:
        print(open(filename).read())
例として挙げた cat() 関数ですが、仮にこの関数が予想に反して URL 指定で何度も呼ばれたら、パフォーマンス的にはどうなるでしょう?
初回の import urllib.request では import の時間が丸々掛かります。これは避けようがありません。
2回目以降の import urllib.request では、初回ほども時間が掛かりません。が、初回ほども掛からないというだけで、import の処理自体は決して軽いものではありません。

この問題を解決するには、2回目以降ならば import を回避することが望まれます。
以下のようにグローバル変数と __import__() 関数を使うことで実現可能です。2回目以降は if文が実行されるだけなので、処理コストはずっと小さくなります。

urllib_request = None  # グローバル変数

def cat(filename):
    if filename.startswith('http://'):
        # 初回のみimportする
        if urllib_request is None:
            global urllib_request
            urllib_request = __import__('urllib.request')  # __import__()を使う

        print(urllib_request.urlopen(filename).read())
    else:
        print(open(filename).read())

0 件のコメント:

コメントを投稿