Python の遅延インポート - 遅延インポートを実装する方法

王林
リリース: 2023-04-20 11:04:06
転載
1248 人が閲覧しました

Python プログラムに大量のインポートがあり、起動が非常に遅い場合は、遅延インポートを試してください。この記事では、遅延インポートを実現する方法を共有します。 PEP0690[1] は、Python コンパイラ (-L) または標準ライブラリにこの機能を追加できるようにすることを提案していますが、現在の Python バージョンではまだ実装されていません。

ご存知のとおり、Python アプリケーションは、ユーザーの実際の操作を実行する前にインポート操作を実行します。モジュールが異なると、異なる場所から取得される可能性があり、実行に非常に時間がかかるモジュールもあれば、そうでないモジュールもある可能性があります。ユーザーが呼び出すものなので、多くのモジュールをインポートするのは純粋に時間の無駄です。

したがって、遅延インポートが必要です。遅延インポートを適用する場合、import foo を実行すると、名前 foo がグローバル完全名前空間 (globals()) に遅延参照として追加されるだけです。コンパイラーは実際のインポート操作を実行しません。 foo にアクセスするコードが見つかるまで実行されます。同様に、from foo import bar は名前空間に bar を追加し、bar を呼び出すコードに遭遇すると foo をインポートします。

実装するコードを書く

それでは、実装するコードをどのように書くのでしょうか?実際、それを実装するためのコードを記述する必要はありません。遅延インポート機能を実装するプロジェクト、つまり TensorFlow がすでに存在します。そのコードはサードパーティのライブラリに依存しません。それをここに置きます。将来遅延インポートが必要な場合は、LazyLoader[2] クラスを直接配置して、それを自分のプロジェクトにコピーするだけです。

ソース コードは次のとおりです。

# Code copied from https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/util/lazy_loader.py
"""A LazyLoader class."""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import importlib
import types


class LazyLoader(types.ModuleType):
"""Lazily import a module, mainly to avoid pulling in large dependencies.

`contrib`, and `ffmpeg` are examples of modules that are large and not always
needed, and this allows them to only be loaded when they are used.
"""

# The lint error here is incorrect.
def __init__(self, local_name, parent_module_globals, name):# pylint: disable=super-on-old-class
self._local_name = local_name
self._parent_module_globals = parent_module_globals

super(LazyLoader, self).__init__(name)

def _load(self):
# Import the target module and insert it into the parent's namespace
module = importlib.import_module(self.__name__)
self._parent_module_globals[self._local_name] = module

# Update this object's dict so that if someone keeps a reference to the
# LazyLoader, lookups are efficient (__getattr__ is only called on lookups
# that fail).
self.__dict__.update(module.__dict__)

return module

def __getattr__(self, item):
module = self._load()
return getattr(module, item)

def __dir__(self):
module = self._load()
return dir(module)
ログイン後にコピー

コードの説明:

クラス LazyLoader は、types.ModuleType から継承し、初期化関数により、遅延モジュールは実際のモジュールのように動作します グローバル変数にも正しく追加されます モジュールが実際に使用されるとき、つまり __getattr__ または __dir__ が実行されるときのみ、実際のモジュールがインポートされ、グローバル変数は次のポイントに更新されます実際のモジュールとそのすべてのステータス (__dict__) 遅延ロードへの参照、モジュールのロードがアクセスされるたびにロード プロセスを経る必要がないように、実際のモジュールの状態に更新されます。

コードの使用法:

通常、モジュールは次のようにインポートします:

import tensorflow.contrib as contrib
ログイン後にコピー

対応する遅延インポートのバージョンは次のとおりです:

contrib = LazyLoader('contrib', globals(), 'tensorflow.contrib')
ログイン後にコピー

PEP0690 推奨されるアプローチ

PEP0690 の提案は、パフォーマンスを向上させるためにコンパイラー (C コード) レベルで実装することです。使用方法は 2 つあります。

One

1 つの方法は、Python スクリプトの実行時に -L パラメーターを追加することです。たとえば、次の内容を含む 2 つのファイル spam.py があります。

##
import time
time.sleep(10)
print("spam loaded")
ログイン後にコピー

egg.py の内容は次のとおりです。

import spam
print("imports done")
ログイン後にコピー

通常のインポート条件では、10 の後に最初に「spamloaded」が出力されます。 python -L Eggs.py を実行すると、スパム モジュールはインポートされず、アプリケーションのスパム モジュールはまったく使用されません。 Egg.py の内容が次の場合:

import spam
print("imports done")
spam
ログイン後にコピー

python -L Egg.py を実行すると、最初に「importsned」が出力され、「spamloaded」が出力されます。 10 秒後に印刷されます)。

Second

もう 1 つの方法は、標準ライブラリの importlib メソッドを呼び出すことです。

import importlib 
importlib.set_lazy_imports(True)
ログイン後にコピー

一部のモジュールで遅延読み込みができない場合は、除外するには、次のようにすることもできます。

import importlib 
importlib.set_lazy_imports(True,excluding=["one.mod", "another"])
ログイン後にコピー

次のようにすることもできます:

from importlib import eager_imports

with eager_imports():
import foo
import bar
ログイン後にコピー

最後の言葉

プロフェッショナルの後 実際の Python コマンド ライン プログラムでテストした後、遅延インポートを適用すると、起動時間が 70% 増加し、メモリ使用量が 40% 削減され、これは非常に印象的です。

参考文献

[1]PEP0690: https://github.com/python/peps/blob/main/pep-0690.rst

[2]LazyLoader : https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/util/lazy_loader.py

以上がPython の遅延インポート - 遅延インポートを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:51cto.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート