国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

妙用Hook來研究Python的Import機(jī)制

開發(fā) 開發(fā)工具
這兩天周末在家學(xué)習(xí)Python,我發(fā)現(xiàn)我們平常接觸最多的也就是import這條語句,這兩天在編寫一些程序的時(shí)候恰恰需要import hook去完成一些操作,借著這個(gè)周末在家閑著沒事兒通過import hook這個(gè)命令,把Python的import機(jī)制了解了一下。

[[181431]]

這兩天周末在家學(xué)習(xí)Python,我發(fā)現(xiàn)我們平常接觸最多的也就是import這條語句,這兩天在編寫一些程序的時(shí)候恰恰需要import hook去完成一些操作,借著這個(gè)周末在家閑著沒事兒通過import hook這個(gè)命令,把Python的import機(jī)制了解了一下。

0x00 Import機(jī)制概述

從名字上可以推斷出,import hook這個(gè)命令是和Python的導(dǎo)入機(jī)制有所關(guān)聯(lián)。再具體一點(diǎn)的話,import hook的作用是把我們自己寫的腳本直接注入到Python導(dǎo)入的例行操作里去。如果還要繼續(xù)往下說的話,那我們首先應(yīng)該來了解一下import默認(rèn)的時(shí)候是如何處理的。

對(duì)于我們來說的話,其實(shí)這個(gè)過程比較簡(jiǎn)單:當(dāng)Python的解釋器遇到import語句的時(shí)候,它回去查閱sys.path里面所有已經(jīng)儲(chǔ)存的目錄。這個(gè)列表初始化的時(shí)候,通常包含一些來自外部的庫(external libraries)或者是來自操作系統(tǒng)的一些庫,當(dāng)然也會(huì)有一些類似于dist-package的標(biāo)準(zhǔn)庫在里面。這些目錄通常是被按照順序或者是直接去搜索想要的:如果說他們當(dāng)中的一個(gè)包含有期望的package或者是module,這個(gè)package或者是module將會(huì)在整個(gè)過程結(jié)束的時(shí)候被直接提取出來。

我們可以寫一段代碼來演示一下ImportError,運(yùn)行下面的代碼的時(shí)候,我們會(huì)catch一個(gè)exception,在程序結(jié)束之前,它可能會(huì)嘗試多個(gè)imports。

  1. #!/usr/bin/env python 
  2. #coding=utf8 
  3. try: 
  4.     # Python 2.7-3.x 
  5.     import json 
  6. except ImportError: 
  7.     try: 
  8.         # Python 2.6 
  9.         import simplejson as json 
  10.     except ImportError: 
  11.         try: 
  12.              from django.utils import simplejson as json 
  13.          except ImportError: 
  14.              raise Exception("Requires a JSON package!"

雖然說這段sample寫的很不beautiful,但是他可以在一定程度上增加我們寫的程序或者package的可以執(zhí)行。慶幸的是我們僅僅需要用這種方式去處理極少數(shù)有價(jià)值的庫,比如說代碼中的Json庫。

0x01 關(guān)于__path__的更多細(xì)節(jié)

上文中提到的Python的Import流在大多數(shù)情況下是想描述一樣有用的,但是事實(shí)上遠(yuǎn)不止這些。他省略了一些我們可以根據(jù)需要調(diào)節(jié)的地方。

首先,__path__這個(gè)屬性是我們可以在__init__.py里面去定義的。你可以認(rèn)為他像一個(gè)sys.path的本地?cái)U(kuò)展并且只服務(wù)于我們導(dǎo)入的package的子模塊。換句話說,它包含目錄時(shí)應(yīng)該尋找一個(gè)package的子模塊被導(dǎo)入。默認(rèn)的情況下只有__init__.py的目錄,但是他可以擴(kuò)展到包含任何其他任何的路徑。

舉一個(gè)典型的例子就是把一些邏輯上的package分割成多個(gè)實(shí)際上的package,其實(shí)就是分割成多個(gè)distribution,一般情況下是不同的pypi包。舉個(gè)例子,讓我們假設(shè)構(gòu)造一個(gè)test.package,里面包含有test.client和test.server,他們?cè)趐ypi注冊(cè)的時(shí)候是按照兩個(gè)不同的distribution去注冊(cè)的,這樣的話用戶可以選擇其中的一個(gè)或多個(gè)distribution去安裝。我們需要設(shè)置test.__path__讓他們?nèi)ブ赶騮est.server和test.client的目錄(如果你只安裝了一個(gè)distribution的話只需要設(shè)置一個(gè))。聽上去好像有點(diǎn)復(fù)雜,實(shí)際上Python有一個(gè)模塊叫做pkgutil,這個(gè)模塊的作用就是讓我們很輕松的去實(shí)現(xiàn)上述的功能,你只需要在test/__init__.py下面添加一下兩行就可以了。

  1. import pkgutil  
  2. __path__ = pkgutil.extend_path(__path__, __name__) 

其實(shí)還有比這個(gè)還簡(jiǎn)單的方法,這里推薦一個(gè)文章給大家:http://doughellmann.com/PyMOTW/

0x02 真·鉤子:sys.meta_path和sys.path_hooks

讓我們繼續(xù),接著我們就會(huì)去分析import的過程,其實(shí)這部分正是這篇文章的重點(diǎn)。截下來說的比如說從zip文件或者是repo里面字節(jié)獲取模塊,或者是動(dòng)態(tài)的去用各種方法建立它們,比如說是web服務(wù)、dll或者是RESTful API等等幾乎你可以想到的任何的方法。我也會(huì)提到一些各個(gè)獨(dú)立模塊之間拿坑爹的交互性,比如說一個(gè)package檢測(cè)到自己被導(dǎo)入的時(shí)候,它能夠適應(yīng)和擴(kuò)展自己的接口。接著我們將會(huì)討論一下Python的安全增強(qiáng)沙箱,這個(gè)沙箱的作用是用來拒絕訪問某些模塊或者是改變其某些功能。

這些功能其實(shí)都可以通過import hooks來實(shí)現(xiàn)。有兩種不同的hook,一種叫做meta hook(sys.meta_path),另一種叫做path hook(sys.path_hooks)。盡管他們?cè)趦蓚€(gè)差不多的導(dǎo)入流的階段被調(diào)用,但是他們被創(chuàng)建的時(shí)候還是會(huì)取決于兩個(gè)東西,一個(gè)叫做模塊查找器(Module Finder),一個(gè)叫做模塊加載器(Module Loader)。

模塊查找器其實(shí)是一種簡(jiǎn)單的用來查找模塊的對(duì)象,他(find_module)的使用方法如下面所示:

  1. finder.find_module(fullname, path=None) 

他需要把一個(gè)完整的模塊的名字當(dāng)做參數(shù)傳進(jìn)去,path則為這個(gè)模塊的路徑。這個(gè)對(duì)象的可以完成以下三件事中的任意一件:

  • 拋出一個(gè)異常,然后完全取消所有的導(dǎo)入流程
  • 返回一個(gè)None,意思是被導(dǎo)入的這個(gè)模塊不能夠被這個(gè)查找器所找到。但是他仍然可以被導(dǎo)入流的下一個(gè)階段所找到,比如說一些自定義的查找器或者是Python的標(biāo)準(zhǔn)導(dǎo)入機(jī)制。
  • 返回一個(gè)加載器對(duì)象用來加載實(shí)際的模塊。

下一個(gè)就是模塊加載器,模塊加載器其實(shí)就是一個(gè)用來加載制定模塊的對(duì)象,它(load_module)的使用方法如下面的代碼所示:

  1. loader.load_module(fullname) 

這里需要在強(qiáng)調(diào)一次,fullname參數(shù)需要傳進(jìn)去一個(gè)我們想要加載的模塊的全名。返回值應(yīng)當(dāng)是一個(gè)模塊的對(duì)象,***的結(jié)果當(dāng)然就是完成導(dǎo)入對(duì)象的操作。需要注意的是,這些模塊可能已經(jīng)被導(dǎo)入了,或者是復(fù)制這些模塊的功能用來返回這些已經(jīng)存在的模塊。下面是這個(gè)函數(shù)的原型:

  1. def load_module(self, fullname): 
  2. if fullname in sys.modules: return sys.modules[fullname] 

如果在這一階段出現(xiàn)了任何錯(cuò)誤,模塊加載器應(yīng)該拋出一個(gè)ImportError的異常

0x03 自己構(gòu)造一個(gè)加載器:

上面這些僅僅是一些理論,其實(shí)吧PEP302標(biāo)準(zhǔn)里面都描述了這些。在實(shí)際當(dāng)中,其實(shí)模塊加載器和模塊查找器可以是同一個(gè)對(duì)象,也就是說find_module可以去return self。舉個(gè)例子,其實(shí)這個(gè)簡(jiǎn)單的hook可以去阻止任何特定的模塊被導(dǎo)入:

  1. #!/usr/bin/env python 
  2. #coding=utf8 
  3. import sys 
  4. class ImportBlocker(object): 
  5.     def __init__(self, *args): 
  6.         self.module_names = args 
  7.     def find_module(self, fullname, path=None): 
  8.         if fullname in self.module_names: 
  9.             return self 
  10.         return None 
  11.     def load_module(self, name): 
  12.         raise ImportError("%s is blocked and cannot be imported" % name
  13. sys.meta_path = [ImportBlocker('httplib')] 

一旦我們?cè)趕ys.meta_path中加載了這個(gè)hook,他就會(huì)去阻止任何導(dǎo)入的新模塊并且檢查他是否存在于我們的列表里。如果我們?nèi)ナ褂肦equest庫的時(shí)候,這個(gè)hook也會(huì)同樣起作用。

Import Request

執(zhí)行這條語句會(huì)失敗,因?yàn)閞equest是在urllib3內(nèi)部使用的,進(jìn)而去限制httplib的使用。但是一個(gè)hook要是沒事兒干總?cè)r截調(diào)用別的模塊似乎沒啥太大的意思,咱們換個(gè)別的玩法。如果說總是拒絕調(diào)用特定的模塊,我們?yōu)樯恫挥靡粋€(gè)warning去代替呢?這樣的話,這個(gè)hook就可以幫我們檢測(cè)被導(dǎo)入到項(xiàng)目當(dāng)中又被棄用的模塊。代碼如下:

  1. # !/usr/bin/env python 
  2. # coding=utf-8 
  3. import logging 
  4. import imp 
  5. import sys 
  6. class WarnOnImport(object): 
  7.     def __init__(self, *args): 
  8.         self.module_names = args 
  9.     def find_module(self, fullname, path=None): 
  10.         if fullname in self.module_names: 
  11.             self.path = path 
  12.             return self 
  13.         return None 
  14.     def load_module(self, name): 
  15.         if name in sys.modules: 
  16.             return sys.modules[name
  17.         module_info = imp.find_module(name, self.path) 
  18.         module = imp.load_module(name, *module_info) 
  19.         sys.modules[name] = module 
  20.         logging.warning("Imported deprecated module %s"name
  21.         return module 
  22. sys.meta_path = [WarnOnImport('getopt''optparse')] 

為了去訪問一個(gè)正常的導(dǎo)入機(jī)制,我們可以嘗試使用imp。它的find_module和load_module函數(shù)和我們要導(dǎo)入的hook具有相同的名字。但是imp提供的功能更強(qiáng)大,比如說還包括了load_source和load_compile這些功能甚至可以從頭來初始化一個(gè)模塊(new_module)。

責(zé)任編輯:武曉燕 來源: elknot
相關(guān)推薦

2024-12-30 08:02:40

2022-02-17 20:34:12

Python短路機(jī)制開發(fā)

2009-09-18 19:14:29

Hook機(jī)制

2021-03-16 21:45:59

Python Resize機(jī)制

2021-08-12 15:45:23

Pythonimport模塊

2024-05-28 12:25:33

Pythonglobals?函數(shù)

2024-12-19 09:00:00

字典視圖對(duì)象Python

2013-12-16 09:44:01

OpenDayLighSDN網(wǎng)絡(luò)轉(zhuǎn)發(fā)

2012-06-14 10:08:18

2022-06-07 08:59:58

hookuseRequestReact 項(xiàng)目

2020-09-25 10:14:54

漏洞

2023-01-03 10:37:22

CSS動(dòng)畫

2025-11-03 04:00:00

2021-10-20 07:36:03

Python構(gòu)造方法

2010-09-26 09:50:36

SQL Where子句

2023-11-27 19:35:01

C++extern

2023-08-01 09:46:57

虛擬鍵盤API

2010-09-08 16:26:26

SQL循環(huán)語句

2025-09-03 09:04:00

AI視覺研究

2022-04-01 07:14:13

模塊Pythonimport
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

亚洲国产免费看| 亚洲中无吗在线| 欧美午夜片在线观看| 欧美特级aaa| 国产一区二区在线观看视频| a级国产乱理论片在线观看99| 日韩欧美在线精品| 最近2019中文字幕第三页视频| 欧美xxxx做受欧美88bbw| 色噜噜狠狠一区二区三区果冻| 大胆高清日本a视频| 国产三级欧美三级日产三级99| 亚洲 欧美 综合 另类 中字| 青青草国产成人99久久| 欧美一区1区三区3区公司| 黄色av成人| 国产三级精品在线不卡| 欧美~级网站不卡| 51成人做爰www免费看网站| 国产精品福利在线观看播放| 国产九九精品视频| 国产精品久久久久9999赢消| 91精品久久久久久久久久久久久久| 国产欧美高清视频在线| 亚州欧美日韩中文视频| 牛牛影视一区二区三区免费看| 欧美国产日韩一区二区| 超碰在线成人| 欧美一级黑人aaaaaaa做受| 一区二区小说| 国产精品毛片a∨一区二区三区|国| 成人免费在线电影网| 久久久久久亚洲精品中文字幕| 日韩精品视频在线看| 国产91精品久久久久久| 精品99在线| 亚洲综合在线播放| 天堂久久久久va久久久久| 神马影院午夜我不卡| 国产一区二区免费视频| 茄子视频成人免费观看| 欧美国产日韩在线观看| av超碰在线| 91精品国产一区二区三区蜜臀| 好吊日av在线| 日韩最新在线视频| 色爱综合av| wwwxx欧美| 国产资源精品在线观看| 日本成人在线免费视频| 亚洲午夜在线电影| 黄色在线播放网站| 最近中文字幕mv在线一区二区三区四区 | 欧美激情中文不卡| 成色在线视频| 欧美性做爰猛烈叫床潮| aa视频在线观看| 欧美精品中文字幕一区| 日韩av自拍| 五月天色一区| 欧美高清一级片在线观看| 中文av在线播放| 亚洲精品99999| 久久丝袜视频| 日本不卡一二三区| 国产日韩欧美在线一区| 香蒸焦蕉伊在线| 亚洲视频欧洲视频| 日本一区二区综合亚洲| 黄色av免费在线播放| 亚洲综合视频在线观看| 三区四区在线视频| 伊人久久精品视频| 国产精品手机在线播放| 久久亚洲一区二区| 久久综合久久久久88| 亚洲综合在线一区| 亚洲天天在线日亚洲洲精| 欧美人妖在线观看| 狼狼综合久久久久综合网| 91在线精品一区二区三区| 中文av在线播放| 一区二区三区动漫| 色综合天天爱| 91国在线高清视频| 欧美午夜精品久久久久久久| 性欧美1819sex性高清| 国产在线一区二区三区| 国产a级毛片一区| 二区在线视频| 韩国一区二区三区视频| av在线日韩国产精品| 亚洲欧美一区二区三区在线 | 亚洲国产精品t66y| 日本最新在线视频| 8x海外华人永久免费日韩内陆视频| 性欧美videos另类喷潮| 成人黄网18免费观看的网站| 亚洲国产精品字幕| 黄色成人91| 九色中文视频| 日韩在线视频网站| 日韩不卡在线观看日韩不卡视频| 一级毛片视频| 欧美超级免费视 在线| 免费av网站大全久久| 毛片免费在线观看| 欧美在线激情网| 91老师国产黑色丝袜在线| 在线播放蜜桃麻豆| 亚洲精品日韩av| 亚洲男人的天堂av| 视频成人永久免费视频| 国产卡一卡二在线| 欧美乱妇一区二区三区不卡视频| 精品国产乱码久久久久久1区2匹| 日韩中文字幕三区| 亚洲性69xxxbbb| 久久精品久久综合| 日本动漫同人动漫在线观看| 国产精品我不卡| 欧美日韩激情视频8区| 欧美毛片免费观看| 妺妺窝人体色www在线观看| 国产一区二区三区欧美| 免费欧美日韩国产三级电影| 久久国产精品一区| 成人黄视频免费| 色视频一区二区| 黄色亚洲免费| 日本不卡不卡| 欧美性bbwbbwbbwhd| 91精品国产品国语在线不卡| 中国女人久久久| 国产鲁鲁视频在线观看特色| 国产精品高清一区二区三区| 色综合咪咪久久| 极品尤物久久久av免费看| 四虎精品成人影院观看地址| 91免费观看网站| 91福利在线导航| 亚洲一区自拍| 青草av在线| 中文字幕制服丝袜在线| 亚洲欧洲日本专区| aa级大片欧美| 视频亚洲一区二区| 加勒比在线日本| 国产精品亚发布| 在线观看欧美日本| 手机精品视频在线观看| 在线视频cao| 无码aⅴ精品一区二区三区浪潮| 欧美精品做受xxx性少妇| 综合亚洲深深色噜噜狠狠网站| 夜夜躁狠狠躁日日躁2021日韩| 中文字幕在线影院| 精品不卡一区二区三区| 亚洲第一区在线| 91在线精品一区二区三区| 欧一区二区三区| 最新中文字幕在线| 欧美一区二区三区四区夜夜大片| 亚洲色图在线观看| 成人免费在线播放视频| 午夜精品视频| 日韩欧美看国产| 日本加勒比高清在线| 国产精品99久久久久久久| 精品国产伦一区二区三区观看体验| 国产精品中文字幕欧美| 久久a爱视频| 美州a亚洲一视本频v色道| 亚洲精品久久区二区三区蜜桃臀| 一本久久综合亚洲鲁鲁| 亚洲欧美偷拍三级| 国产亚洲一区在线| 日韩三级一区| 中文在线天堂网| 亚洲一区二区三区免费观看| 美日韩精品免费观看视频| 红桃视频成人在线观看| 捆绑调教一区二区三区| 成人自拍在线| 老司机在线永久免费观看| 欧美不卡在线播放| 国产成人+综合亚洲+天堂| 欧美一三区三区四区免费在线看| 97久久人人超碰| 亚洲影视一区| 久久亚洲精品爱爱| 一不卡在线视频| 真人做人试看60分钟免费| 国产高清在线不卡| 亚洲美女性视频| 日韩欧美第一页| 国产91精品入口| 欧美在线1区| 18国产精品| 女子免费在线观看视频www|