目錄
寫程式碼實作
PEP0690 建議的做法
最後的話
參考資料
首頁 後端開發 Python教學 如何實現 Python 的惰性導入-lazy import

如何實現 Python 的惰性導入-lazy import

Apr 20, 2023 am 11:04 AM
python 應用程式 模組

如果你的 Python 程式程式有大量的 import,而且啟動非常慢,那麼你應該嘗試懶導入,本文分享一種實現惰性導入的一種方法。雖然 PEP0690[1] 已經提案讓 Python 編譯器(-L) 或標準函式庫加入這個功能,但目前的 Python 版本還未實現。

眾所周知,Python 應用程式在執行使用者的實際操作之前,會執行import 操作,不同的模組可能來自不同的位置,某些模組的運作可能非常耗時,某些模組可能根本不會被用戶調用,因此許多模組的導入純粹是浪費時間。

因此我們需要惰性導入,當應用惰性導入時,執行import foo 只會把名字foo 加到全域的全名空間(globals())中當一個懶引用(lazy reference),編譯器遇到任何存取foo 的程式碼時才會執行真正的import 操作。類似的,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__ 時,才會真正的import 實際模組,更新全域變數以指向實際模組,並且將其所有狀態(__dict__)更新為實際模組的狀態,以便對延遲載入的引用,載入模組不需要每次存取都經過載入過程。

程式碼使用:

正常情況下我們這樣導入模組:

import tensorflow.contrib as contrib
登入後複製

其對應的惰性導入版本如下:

contrib = LazyLoader('contrib', globals(), 'tensorflow.contrib')
登入後複製

PEP0690 建議的做法

PEP0690 的提案是在編譯器( C 程式碼)層面實現,這樣效能會更好。其使用方法有兩種。

其一

一種方式是執行Python 腳本時加入-L 參數,例如有兩個檔案spam.py 內容如下:

import time
time.sleep(10)
print("spam loaded")
登入後複製

egg.py 內容如下:

import spam
print("imports done")
登入後複製

#正常導入情況下,會等10 秒後先列印"spam loaded",然後列印"imports done",執行 python -L eggs.py 時,spam 模組永遠不會導入,應用spam 模組壓根就沒有用到。如果 egg.py 內容如下:

import spam
print("imports done")
spam
登入後複製

當執行 python -L eggs.py 時會先列印 "imports done",10 秒之後列印 "spam loaded")。

其二

另一種方式是呼叫標準函式庫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 的惰性導入-lazy import的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

HadiDB:Python 中的輕量級、可水平擴展的數據庫 HadiDB:Python 中的輕量級、可水平擴展的數據庫 Apr 08, 2025 pm 06:12 PM

HadiDB:輕量級、高水平可擴展的Python數據庫HadiDB(hadidb)是一個用Python編寫的輕量級數據庫,具備高度水平的可擴展性。安裝HadiDB使用pip安裝:pipinstallhadidb用戶管理創建用戶:createuser()方法創建一個新用戶。 authentication()方法驗證用戶身份。 fromhadidb.operationimportuseruser_obj=user("admin","admin")user_obj.

2小時的Python計劃:一種現實的方法 2小時的Python計劃:一種現實的方法 Apr 11, 2025 am 12:04 AM

2小時內可以學會Python的基本編程概念和技能。 1.學習變量和數據類型,2.掌握控制流(條件語句和循環),3.理解函數的定義和使用,4.通過簡單示例和代碼片段快速上手Python編程。

Navicat查看MongoDB數據庫密碼的方法 Navicat查看MongoDB數據庫密碼的方法 Apr 08, 2025 pm 09:39 PM

直接通過 Navicat 查看 MongoDB 密碼是不可能的,因為它以哈希值形式存儲。取回丟失密碼的方法:1. 重置密碼;2. 檢查配置文件(可能包含哈希值);3. 檢查代碼(可能硬編碼密碼)。

Python:探索其主要應用程序 Python:探索其主要應用程序 Apr 10, 2025 am 09:41 AM

Python在web開發、數據科學、機器學習、自動化和腳本編寫等領域有廣泛應用。 1)在web開發中,Django和Flask框架簡化了開發過程。 2)數據科學和機器學習領域,NumPy、Pandas、Scikit-learn和TensorFlow庫提供了強大支持。 3)自動化和腳本編寫方面,Python適用於自動化測試和系統管理等任務。

如何針對高負載應用程序優化 MySQL 性能? 如何針對高負載應用程序優化 MySQL 性能? Apr 08, 2025 pm 06:03 PM

MySQL數據庫性能優化指南在資源密集型應用中,MySQL數據庫扮演著至關重要的角色,負責管理海量事務。然而,隨著應用規模的擴大,數據庫性能瓶頸往往成為製約因素。本文將探討一系列行之有效的MySQL性能優化策略,確保您的應用在高負載下依然保持高效響應。我們將結合實際案例,深入講解索引、查詢優化、數據庫設計以及緩存等關鍵技術。 1.數據庫架構設計優化合理的數據庫架構是MySQL性能優化的基石。以下是一些核心原則:選擇合適的數據類型選擇最小的、符合需求的數據類型,既能節省存儲空間,又能提升數據處理速度

如何將 AWS Glue 爬網程序與 Amazon Athena 結合使用 如何將 AWS Glue 爬網程序與 Amazon Athena 結合使用 Apr 09, 2025 pm 03:09 PM

作為數據專業人員,您需要處理來自各種來源的大量數據。這可能會給數據管理和分析帶來挑戰。幸運的是,兩項 AWS 服務可以提供幫助:AWS Glue 和 Amazon Athena。

redis怎麼啟動服務器 redis怎麼啟動服務器 Apr 10, 2025 pm 08:12 PM

啟動 Redis 服務器的步驟包括:根據操作系統安裝 Redis。通過 redis-server(Linux/macOS)或 redis-server.exe(Windows)啟動 Redis 服務。使用 redis-cli ping(Linux/macOS)或 redis-cli.exe ping(Windows)命令檢查服務狀態。使用 Redis 客戶端,如 redis-cli、Python 或 Node.js,訪問服務器。

redis怎麼讀取隊列 redis怎麼讀取隊列 Apr 10, 2025 pm 10:12 PM

要從 Redis 讀取隊列,需要獲取隊列名稱、使用 LPOP 命令讀取元素,並處理空隊列。具體步驟如下:獲取隊列名稱:以 "queue:" 前綴命名,如 "queue:my-queue"。使用 LPOP 命令:從隊列頭部彈出元素並返回其值,如 LPOP queue:my-queue。處理空隊列:如果隊列為空,LPOP 返回 nil,可先檢查隊列是否存在再讀取元素。

See all articles