詳解Python import機制(一):import中的基本概念

2021-02-23 碼農升級

簡介

簡單來看,import 機制可以導入我們需要使用的庫,避免代碼重複,使用方便,可謂是編寫 Python 時最常使用寫法,但我們了解 import 嗎?

import 其實有很多容易混淆的概念以及可以實現很多非常有趣的玩法,本篇文章拋磚引玉,聊聊 import

需注意,Python2 與 Python3 的 import 機制有較大差別,主要體現在兩點:

簡單而言,Python3.7 與 Python2.7 在 import 機制上有較大差異,這裡以Python3.7 為基準進行討論。

模塊、常規包與命名空間包

「模塊」、「常規包」與「命名空間包」是理解import機制繞不開的概念。

「模塊」:一個以「.py」為後綴的文件就是一個模塊「常規包」:「__init__.py」所在目錄就是一個常規包「命名空間包」:命名空間包是一種虛擬的概念,它由多個子包構成,這些子包可以在任意位置,可以為 zip 中的文件或網絡上的文件,這些子包在概念上是一個整體,這個整體就是一個命名空間包

「常規包」與「命名空間包」的概念在 PEP420 被提出,在 Python3.3 及之後的 Python 版本中實現,此前只有「常規包」這一種包。

import導入系統

通過 import 機制,我們可以使用導入模塊內的代碼。

import 是最常用的導入機制,但並不是唯一的方式,importlib 模塊以及內置的__import__() 方法都可以實現模塊的導入。

import 語句做的是兩個操作

1.搜索操作:在相應的路徑中搜索指定名稱的模塊2.綁定操作:將搜索到的結果綁定到當前作用域對應的名稱上(即創建module對象,並初始化)

通過閱讀 Python 官方文檔可知,import 的搜索操作通過 __import__() 方法實現,而綁定操作只有 import 語句才能做到。

當某個模塊初次被 import 時,Python 會在相應的路徑去搜索該模塊,如果模塊存在,則在當前作用域下創建一個 module 對象並進行初始化,如果未找到,則拋出 ModuleNotFoundError。

import 在導入模塊時,會根據 sys.path 中定義的路徑來搜索對應的模塊,sys.path 是一個 list,import 時會先從 sys.path 中下標為 0 的路徑開始搜索,我們可以將需要的路徑添加到 sys.path。

如果我們沒有修改,sys.path 中默認的路徑為:

要修改搜索路徑有3種方式:

動態修改 sys.path,因為 sys.path 為 list,所以我們可以很輕鬆的操作 list 實現搜索路徑的修改。這種方式只會對當前項目臨時生效

修改 PYTHONPATH 環境變量,這種方式會永久生效,而且所有的 Python 項目都會受到影響,因為 Python 程序啟動時會自動去讀取該環境良好的值。

增加 .pth 後綴的文件。在 sys.path 已有的某一個目錄下添加 .pth 後綴的配置文件,該文件的內容就是要添加的搜索路徑,Python 在遍歷已有目錄的過程中,如果遇到 .pth 文件,就會將其中的路徑添加到 sys.path 中。

Python 中定義了多種搜索策略去搜索相應的模塊,而這些策略可以通過 importlib 等提供的各類 hook 進行修改實現一些有趣的效果。

在 Python3.3 之後,所有的模塊導入機制都會通過「sys.meta_path」暴露,不會在有任何隱式導入機制。

In [1]: import sys

In [2]: sys.meta_path

Out[2]:

[_frozen_importlib.BuiltinImporter,

_frozen_importlib.FrozenImporter,

_frozen_importlib_external.PathFinder,

<six._SixMetaPathImporter at 0x10f43e860>]

import形式

import 主要有兩種形式

1.import xxx

2.from xxx import xxx

可以看到下面的例子:

In [1]: import os

In [2]: from os.path import join

In [3]: import os.path.join

ModuleNotFoundError Traceback (most recent call last)

<ipython-input-3-26fe2f8f50ea> in <module>

----> 1 import os.path.join

ModuleNotFoundError: No module named 'os.path.join'; 'os.path' is not a package

可以看出,第2行與第3行的區別在於是否使用 from,其背後的規則是:

在導入模塊的過程中,首先會搜索sys.modules中內容,sys.modules是模塊的緩存,其中包括了所有此前導入的模塊。

使用的是 import A, 此時會先檢查sys.moduels中是否存在A,如果存在,則不會再去搜索加載,而是直接從緩存中取來用,如果沒有,則搜索模塊並進行綁定操作,隨後便將其加載到sys.modules中

使用的是 from A import B,此時依舊會先檢查A並進行相同的操作,隨後獲得A的module對象後,從中解析並尋找B然後再填充到A的__dict__結構中,從而實現不用標明來自於A,直接通過B的名稱就可直接使用的B的效果。

相對導入與絕對導入

當我們import導入模塊或包時,Python提供兩種導入方式:

1.相對導入 relative import2.絕對導入 absolute import

在 Python2.5 之前,Python 默認使用的相對導入,而 Python2.5 之後,以絕對導入為默認使用的導入方式。

這兩個概念與相對路徑、絕對路徑的概念有些相似,幾個具體的例子:

1.絕對導入格式為:import A.B.C 或者 form A.B import C2.相對導入格式為:from . import B 或 from ..A import B,其中.表示當前模塊,..表示上層模塊(與相對路徑概念類似)

在開發第三方模塊時,通常使用相對導入的形式,這可以有效避免硬編碼帶來的問題,比如在開發過程中,我們修改了某個文件的名稱,此時,使用絕對導入形式的 import 就需要修改相應的名稱。這其實也不是絕對的,當包的結構發生改變時,相對導入就會出現問題,當相對模塊名稱的改變而言,目錄結構的改變出現概率會小一些。

import 中的基本概念就簡單介紹到這裡,這些概念中還有很多細節值得學習。

相關焦點

  • 詳解Python import機制(上):import中的基本概念
    作者 |  ayuliao來源 | hackpython(ID: hackpython)簡介簡單來看,import機制可以導入我們需要使用的庫,避免代碼重複,使用方便,可謂是編寫Python時最常使用寫法,但我們了解import嗎?
  • 詳解Python中的import的用法
    import語句用來導入其他python文件(稱為模塊module),使用該模塊裡定義的類、方法或者變量,從而達到代碼復用的目的。為了方便說明,我們用實例來說明import的用法,讀者朋友可以跟著嘗試(嘗試時建議使用python3,python2和python3在import的表現有差異,之後會提到)。
  • 深入探討 Python 的 import 機制
    對於這些基礎的概念,對於新手還是有必要介紹一下它們的區別。模塊:類似 *.py,*.pyc, *.pyd ,*.so,*.dll 這樣的文件,是 Python 代碼載體的最小單元。__import__ 的妙用在 Python 中使用 import 關鍵字來實現模塊/包的導入,可以說是基礎中的基礎。但這不是唯一的方法,還有 importlib.import_module() 和 __import__() 等。對於 __import__ ,普通的開發者,可能就會比較陌生。
  • Python Import 機制與拓展——劉暢@PyCon 2015 China
    在真正的將python應用到實際的項目中,你會遇到一些無法避免的問題。最讓人困惑不解的問題有二類,一個 編碼問題,另一個則是引用問題。本文主要討論關於Python中import的機制、實現、以及介紹一些有意思的Python Hooks。
  • 初窺 Python 的 import 機制
    作者:pwwang一、前言 本文基於開源項目:https://github.com/pwwang/python-import-system補充擴展講解,希望能夠讓讀者一文搞懂 Python 的 import
  • Python中from import和import的區別?沒有比這更好的回答了
    ps:使用的python3.5版本。
  • Python入門基礎之導入問題:from import 與import 詳解
    在python中導入模塊絕對是我們最最常用的功能,基本每個py文件中都會有import或者是from import語句。可是,這兩種導入方法有什麼不同,又該怎麼用呢?今天就好好來分析一下。Import工作方式:其中,導入程序搜索的目錄如下:import解釋:解釋器執行到import語句, 如果在搜索路徑中找到了指定的模塊, 就會加載它。
  • python基礎--自定義模塊、import、from......import......
    如果你退出python解釋器然後重新進入,那麼你之前定義的函數或者變量都將丟失,因此我們通常將程序寫到文件中以便永久保存下來,需要時就通過python test.py方式去執行,此時test.py被稱為腳本script。所以,腳本就是一個python文件,比如你之前寫的購物車,模擬博客園登錄系統的文件等等。3.模塊的分類Python語言中,模塊分為三類。
  • python 模塊相互import
    模塊A中import B,而在模塊B中import A。這時會怎麼樣呢?
  • 你對Python裡的import一無所知
    Python 3 中默認為 0,表示僅支持 absolute import。如果大於 0,則表示相對導入的父目錄的級數,即 1 類似於 '.',2 類似於 '..'。gt;> myos<module 'sep' from '/usr/lib64/python2.7/os.pyc'>>>> myos.getcwd()'/home/wangbm'從 python 3 開始,內建的 reload 函數被移到了 imp 模塊中。
  • 徹底搞懂Python 中的 import 與 from import
    什麼時候用import xxx?什麼時候用from xxx import yyy?什麼時候用from xxx.yyy import zzz?什麼時候用from xxx import *?這篇文章,我們來徹底搞懂這個問題。
  • Python 的 import 居然這麼有料
    一、前言 本文基於開源項目:https://github.com/pwwang/python-import-system補充擴展講解,希望能夠讓讀者一文搞懂 Python 的 import 機制。1.1 什麼是 import 機制?
  • Python import 導入上一級模塊
    1.導入同級模塊python導入同級模塊(在同一個文件夾中的py文件)直接導入即可。import xxx如在file1.py中想導入file2.py,注意無需加後綴".py":import file2# 使用file2中函數時需加上前綴"file2."
  • Python ImportError 解決思路
    辛辛苦苦安裝完了python3.8,最後再運行的時候會出現ImportError: No module named configparser的報錯,參考了很多資料,未能解決問題,後來突然想到原來之前安裝過python2.7版本,對於python來說2.x版本與3.x版本中模塊的名稱是不一樣的
  • 1 小時逼瘋面試者:聊聊 Python Import System?
    不過既然要開始聊,那我們先得在縷清「Python Import System」的整體流程是什麼樣的一、基礎概念1. 什麼可以被import?-- Python中的基本概念在介紹Import System之前,我們要了解的是在Python中什麼可以被import。
  • Python模塊import本質是什麼?
    寫這篇文章主要是對Python的import模塊或包的機制有了更深層級的一個理解,也在具體工作中得到了一點實踐,這種思考是由上一篇文章
  • Python 中的 import 與 from import 到底啥意思?
    什麼時候用import xxx?什麼時候用from xxx import yyy?什麼時候用from xxx.yyy import zzz?什麼時候用from xxx import *?這篇文章,我們來徹底搞懂這個問題。
  • 如何 Import 自定義的 Python 模塊?
    經常要用的功能能不能像導入python模塊一樣,通過import導入呢?背景在實際的工作過程中,經常會用到一個功能,如果每次編寫代碼的時候都進行重新編寫或者打開已經編寫好的函數進行複製粘貼,這樣就顯得很麻煩,有沒有什麼方法可以像導入python模塊的那樣,直接把要用的函數以模塊名+方法的形式調用呢?
  • 《面試官一個小時逼瘋面試者》之聊聊Python Import System?
    不過既然要開始聊,那我們先得在縷清「Python Import System」的整體流程是什麼樣的一、基礎概念1. 什麼可以被import?-- Python中的基本概念在介紹Import System之前,我們要了解的是在Python中什麼可以被import。
  • 慢步python,說說import,引用功能代碼(功能庫、py文件代碼)
    今天慢步休息,繼續學習python語言。其實慢步已經將基礎和必要的python語言知識點寫了。今天想說說importimport是python語言的保留字,它能實現引用當前程序之外已有的功能代碼。python語言像積木,你可以根據你想要的功能,編寫一系列的代碼。比如筆者之前編寫的《word文檔標題置換》。