介紹importlib

Python將importlib做爲標準庫提供。它旨在提供Pythonimport語法和(__import__()函數)的實現。另外,importlib提供了開發者能夠建立本身的對象(即importer)來處理導入過程。python

那麼imp呢?還有一個imp模塊提供了import語句接口,不過這個模塊在Python3.4已經deprecated了。建議使用importlib來處理。函數

這個模塊比較複雜,文中咱們主要探討以下主題:學習

  • 動態導入
  • 檢查模塊是否能夠導入
  • 從源文件導入

咱們先從動態導入開始。spa

動態導入

importlib模塊支持傳遞字符串來導入模塊。咱們先來建立一些簡單模塊一遍演示。咱們在模塊裏提供了相同接口,經過打印它們自身名字來區分。咱們分別建立了foo.pybar.py,代碼以下:orm

def main():
    print(__name__)

如今咱們盡須要使用importlib導入它們。咱們來看看代碼是如何實現的,確保該代碼在剛纔建立的兩個文件的相同目錄下。對象

#importer
import importlib def dynamic_import(module): return importlib.import_module(module) if __name__ == "__main__": module = dynamic_import('foo') module.main() module2 = dynamic_import('bar') module2.main() 

這裏咱們導入importlib模塊,並建立了一個很是簡單的函數dynamic_import。這個函數直接就調用了importlib的import_module方法,並將要導入的模塊字符串傳遞做爲參數,最後返回其結果。而後在主入口中咱們分別調用了各自的main方法,將打印出各自的name.接口

$ python3 importer.py 
foo
bar

也許你不多會代碼這麼作,不過在你須要試用字符串做爲導入路徑的話,那麼importlib就有用途了。ci

模塊導入檢查

Python有個衆所周知的代碼風格EAFP: Easier to ask forgiveness than permission.它所表明的意思就是老是先確保事物存在(例如字典中的鍵)以及在犯錯時捕獲。若是咱們在導入前想檢查是否這個模塊存在而不是靠猜。 使用mportlib就能實現。開發

import importlib.util def check_module(module_name): """  Checks if module can be imported without actually  importing it  """ module_spec = importlib.util.find_spec(module_name) if module_spec is None: print("Module: {} not found".format(module_name)) return None else: print("Module: {} can be imported".format(module_name)) return module_spec def import_module_from_spec(module_spec): """  Import the module via the passed in module specification  Returns the newly imported module  """ module = importlib.util.module_from_spec(module_spec) module_spec.loader.exec_module(module) return module if __name__ == '__main__': module_spec = check_module('fake_module') module_spec = check_module('collections') if module_spec: module = import_module_from_spec(module_spec) print(dir(module)) 

這裏我導入了importlib的子模塊util。check_module裏面調用find_spec方法, 傳遞該模塊字符串做爲參數。當咱們分別傳入了一個不存在和存在的Python模塊。你能夠看到當你傳入不存在的模塊時,find_spec函數將返回 None,在咱們代碼裏就會打印提示。若是存在咱們將返回模塊的specification。文檔

咱們能夠經過該模塊的specification來實際導入該模塊。或者你直接將字符串做爲參數調用import_module函數。不過我這裏也學習如何試用模塊specification方式導入。看看import_module_from_spec函數。它接受check_module提供的模塊specification做爲參數。而後咱們將它傳遞給了module_from_spec函數,它將返回導入模塊。Python文檔推薦導入後而後執行模塊,因此接下來咱們試用exec_module函數執行。最後咱們使用dir來確保獲得預期模塊。

從源代碼導入

importlib的子模塊有個很好用的技巧我想提提。你可使用util經過模塊的名字和路徑來導入模塊。

import importlib.util def import_source(module_name): module_file_path = module_name.__file__ module_name = module_name.__name__ module_spec = importlib.util.spec_from_file_location( module_name, module_file_path ) module = importlib.util.module_from_spec(module_spec) module_spec.loader.exec_module(module) print(dir((module))) msg = 'The {module_name} module has the following methods {methods}' print(msg.format(module_name=module_name, methods=dir(module))) if __name__ == "__main__": import logging import_source(logging) 

在上面的代碼中,咱們實際導入logging模塊,並將模塊傳遞給了import_source函數。這樣咱們就能夠經過導入的模塊獲取到實際的路 徑和名字。而後咱們將信息傳遞給sec_from_file_location函數,它將返回模塊的specification。也了這個咱們就能夠在前 面那樣直接經過importlib導入了。

總結

目前,你知道如何在代碼中使用importlib和import鉤子。這個模塊內容很是多,若是你想自定義importer或者loader,那麼你能夠經過官方文檔或者源代碼瞭解更多。

相關文章
相關標籤/搜索