每天資訊Python 炫技操作:花式導包的八種方法

菜單

Python 炫技操作:花式導包的八種方法

今天這篇文章,跟大家分享 8 種匯入模組的方法。

直接 import

>

>>

import

os

>>> os。getcwd()

‘/home/wangbm’

與此類似的還有,不再細講

import

。。。

import

。。。

as

。。。

from

。。。

import

。。。

from

。。。

import

。。。

as

。。。

一般情況下,使用

import

語句匯入模組已經夠用的。

但是在一些特殊場景中,可能還需要其他的匯入方式。

下面我會一一地給你介紹。

使用 __import__

__import__

函式可用於匯入模組,import 語句也會呼叫函式。其定義為:

__

import__

name

[, globals[, locals[, fromlist[, level]

]]])

引數介紹:

name (required): 被載入 module 的名稱

globals (optional): 包含全域性變數的字典,該選項很少使用,採用預設值 global()

locals (optional): 包含區域性變數的字典,內部標準實現未用到該變數,採用預設值 - local()

fromlist (Optional): 被匯入的 submodule 名稱

level (Optional): 匯入路徑選項,Python 2 中預設為 -1,表示同時支援 absolute import 和 relative import。Python 3 中預設為 0,表示僅支援 absolute import。如果大於 0,則表示相對匯入的父目錄的級數,即 1 類似於 ‘。’,2 類似於 ‘。。’。

使用示例如下:

>>> os = __import__(

‘os’

>>> os。getcwd()

‘/home/wangbm’

如果要實現

import xx as yy

的效果,只要修改左值即可

如下示例,等價於

import os as myos

>>> myos = __import__(

‘os’

>>> myos。getcwd()

‘/home/wangbm’

使用 importlib

importlib 是 Python 中的一個標準庫,importlib 能提供的功能非常全面。

它的簡單示例:

>>>

import

importlib

>>> myos=importlib。import_module(

“os”

>>> myos。getcwd()

‘/home/wangbm’

如果要實現

import xx as yy

效果,可以這樣

>>>

import

importlib

>>>

>>> myos = importlib。import_module(

“os”

>>> myos。getcwd()

‘/home/wangbm’

使用 imp

imp

模組提供了一些 import 語句內部實現的介面。例如模組查詢(find_module)、模組載入(load_module)等等(模組的匯入過程會包含模組查詢、載入、快取等步驟)。可以用該模組來簡單實現內建的

__import__

函式功能:

>>>

import

imp

>>> file, pathname, desc = imp。find_module(

‘os’

>>> myos = imp。load_module(

‘sep’

, file, pathname, desc)

>>> myos

‘sep’

from

‘/usr/lib64/python2。7/os。pyc’

>

>>> myos。getcwd()

‘/home/wangbm’

從 python 3 開始,內建的 reload 函式被移到了 imp 模組中。而從 Python 3。4 開始,imp 模組被否決,不再建議使用,其包含的功能被移到了 importlib 模組下。即從 Python 3。4 開始,importlib 模組是之前 imp 模組和 importlib 模組的合集。

使用 execfile

在 Python 2 中有一個 execfile 函式,利用它可以用來執行一個檔案。

語法如下:

execfile

filename

[, globals[, locals]

])

引數有這麼幾個:

filename:檔名。

globals:變數作用域,全域性名稱空間,如果被提供,則必須是一個字典物件。

locals:變數作用域,區域性名稱空間,如果被提供,可以是任何對映物件。

>>> execfile(

“/usr/lib64/python2。7/os。py”

>>>

>>> getcwd()

‘/home/wangbm’

使用 exec

execfile

只能在 Python2 中使用,Python 3。x 裡已經刪除了這個函式。

但是原理值得借鑑,你可以使用 open … read  讀取檔案內容,然後再用 exec 去執行模組。

示例如下:

>>>

with

open(

“/usr/lib64/python2。7/os。py”

“r”

as

f:

。。。     exec(f。read())

。。。

>>> getcwd()

‘/home/wangbm’

import_from_github_com

有一個包叫做

import_from_github_com

,從名字上很容易得知,它是一個可以從 github 下載安裝並匯入的包。為了使用它,你需要做的就是按照如下命令使用pip 先安裝它。

$

python3 -m pip install import_from_github_com

這個包使用了PEP 302中新的引入鉤子,允許你可以從github上引入包。這個包實際做的就是安裝這個包並將它新增到本地。你需要 Python 3。2 或者更高的版本,並且 git 和 pip 都已經安裝才能使用這個包。

pip 要保證是較新版本,如果不是請執行如下命令進行升級。

$ python3 -m pip install ——upgrade pip

確保環境 ok 後,你就可以在 Python shell 中使用 import_from_github_com

示例如下

>>>

from

github_com。zzzeek

import

sqlalchemy

Collecting git+https://github。com/zzzeek/sqlalchemy

Cloning https://github。com/zzzeek/sqlalchemy to /tmp/pip-acfv7t06-build

Installing collected packages: SQLAlchemy

Running setup。py install

for

SQLAlchemy 。。。 done

Successfully installed SQLAlchemy

-1。1。0

b1。dev0

>>> locals()

{

‘__builtins__’

: 

‘builtins’

(built-

in

)>,

‘__spec__’

None

‘__package__’

None

‘__doc__’

None

‘__name__’

‘__main__’

‘sqlalchemy’

: 

‘sqlalchemy’

from

‘/usr/local/lib/python3。5/site-packages/\

sqlalchemy/__init__。py’

>,

‘__loader__’

: <

class

_frozen_importlib

BuiltinImporter

’>}

>>>

看了 import_from_github_com的原始碼後,你會注意到它並沒有使用importlib。實際上,它的原理就是使用 pip 來安裝那些沒有安裝的包,然後使用Python的

__import__()

函式來引入新安裝的模組。

遠端匯入模組

我在這篇文章裡(

深入探討 Python 的 import 機制:實現遠端匯入模組

),深入剖析了匯入模組的內部原理,並在最後手動實現了從遠端伺服器上讀取模組內容,並在本地成功將模組匯入的匯入器。

具體內容非常的多,你可以點選

這個連結

進行深入學習。

示例程式碼如下:

# 新建一個 py 檔案(my_importer。py),內容如下

import

sys

import

importlib

import

urllib。request

as

urllib2

class

UrlMetaFinder

(importlib。abc。MetaPathFinder)

def

__init__

(self, baseurl)

self。_baseurl = baseurl

def

find_module

(self, fullname, path=None)

if

path

is

None

baseurl = self。_baseurl

else

# 不是原定義的url就直接返回不存在

if

not

path。startswith(self。_baseurl):

return

None

baseurl = path

try

loader = UrlMetaLoader(baseurl)

return

loader

except

Exception:

return

None

class

UrlMetaLoader

(importlib。abc。SourceLoader)

def

__init__

(self, baseurl)

self。baseurl = baseurl

def

get_code

(self, fullname)

f = urllib2。urlopen(self。get_filename(fullname))

return

f。read()

def

get_data

(self)

pass

def

get_filename

(self, fullname)

return

self。baseurl + fullname +

‘。py’

def

install_meta

(address)

finder = UrlMetaFinder(address)

sys。meta_path。append(finder)

並且在遠端伺服器上開啟 http 服務(為了方便,我僅在本地進行演示),並且手動編輯一個名為 my_info 的 python 檔案,如果後面匯入成功會列印

ok

$

mkdir httpserver &&

cd

httpserver

$

cat>my_info。py

name=‘wangbm’

print(‘ok’)

EOF

$

cat my_info。py

name=‘wangbm’

print(‘ok’)

$

$

python3 -m http。server 12800

Serving HTTP on 0。0。0。0 port 12800 (http://0。0。0。0:12800/) 。。。

。。。

一切準備好,驗證開始。

>>>

from

my_importer

import

install_meta

>>> install_meta(

‘http://localhost:12800/’

# 往 sys。meta_path 註冊 finder

>>>

import

my_info

# 列印ok,說明匯入成功

ok

>>> my_info。name

# 驗證可以取得到變數

‘wangbm’

好了,8 種方法都給大家介紹完畢,對於普通開發者來說,其實只要掌握 import 這種方法足夠了,而對於那些想要自己開發框架的人來說,深入學習 __import__ 以及 importlib 是非常有必要的。

關注柒柒分享更多有趣的python知識!