產(chǎn)品詳情
131558 遠(yuǎn)程I/O UR20-1CNT-500魏德米勒模塊
上海泉心電氣設(shè)備有限公司主營(yíng)菲尼克斯/phoenix contact(鳳凰);魏德米勒weidmuller;曼耐柯斯mennekes;萬可WAGO;等德國(guó)進(jìn)口元器件產(chǎn)品。
131558 遠(yuǎn)程I/O UR20-1CNT-500魏德米勒模塊
1315390000UR20-16DI-N遠(yuǎn)程IO 1315210000UR20-16DI-P-PLC-INT遠(yuǎn)程I/O 1315270000UR20-16DO-P-PLC-INT遠(yuǎn)程I/O 1315670000UR20-8AI-I-PLC-INT遠(yuǎn)程I/O 1315370000UR20-8DI-N-3W遠(yuǎn)程IO 1315430000UR20-8DO-N遠(yuǎn)程IO 1346610000UR20-EBK-ACC遠(yuǎn)程I/O 1334890000UR20-FBC-CAN遠(yuǎn)程IO 1334900000UR20-FBC-DN遠(yuǎn)程IO 1339920000UR20-SM-ACC遠(yuǎn)程I/O 1791452000電子產(chǎn)品SAI-4/6/8-MHF4PPUR20M 1791462000電子產(chǎn)品SAI-4/6/8-MHF5PPUR20M 1525820000遠(yuǎn)程I/OPWZ-UR20-HD 1315400000遠(yuǎn)程I/OUR20-16DI-N-PLC-INT 1315450000遠(yuǎn)程I/OUR20-16DO-N-PLC-INT 1315580000遠(yuǎn)程I/OUR20-1CNT-500 2007430000遠(yuǎn)程I/OUR20-1COM-SAI-PRO 1990070000遠(yuǎn)程I/OUR20-2AI-SG-24-DIAG 2007420000遠(yuǎn)程I/OUR20-3EM-230V-AC 1993880000遠(yuǎn)程I/OUR20-4AI-UI-DIF-16-DIAG 1315740000遠(yuǎn)程I/OUR20-4COM-IO-LINK 1550070000遠(yuǎn)程I/OUR20-4DI-2W-230V-AC 2464570000遠(yuǎn)程I/OUR20-4DI-4DO-PN-FSPS-V2 1315350000遠(yuǎn)程I/OUR20-4DI-N 1315410000遠(yuǎn)程I/OUR20-4DO-N 1315420000遠(yuǎn)程I/OUR20-4DO-N-2A 1315720000遠(yuǎn)程I/OUR20-8AI-I-16-DIAG-HD 1315650000遠(yuǎn)程I/OUR20-8AI-I-16-HD 2555940000遠(yuǎn)程I/OUR20-8AI-RTD-DIAG-2W 2464590000遠(yuǎn)程I/OUR20-8DI-PN-FSPS-V2 2614380000遠(yuǎn)程I/OUR20-FBC-PB-DP-V2 1334940000遠(yuǎn)程I/OUR20-FBC-PL 2566380000遠(yuǎn)程I/OUR20-FBC-PN-IRT-V2 1334770000遠(yuǎn)程IOUR20-16AUX-I 1334780000遠(yuǎn)程IOUR20-16AUX-O 1315200000遠(yuǎn)程IOUR20-16DI-P 1315440000遠(yuǎn)程IOUR20-16DO-N 1315250000遠(yuǎn)程IOUR20-16DO-P 1315570000遠(yuǎn)程IOUR20-1CNT-100-1DO 1315750000遠(yuǎn)程IOUR20-1COM-232-485-422 1508090000遠(yuǎn)程IOUR20-1SSI 1315590000遠(yuǎn)程IOUR20-2CNT-100 1315610000遠(yuǎn)程IOUR20-2PWM-PN-2A 1315700000遠(yuǎn)程IOUR20-4AI-RTD-DIAG 1315710000遠(yuǎn)程IOUR20-4AI-TC-DIAG 1394390000遠(yuǎn)程IOUR20-4AI-UI-12 1315620000遠(yuǎn)程IOUR20-4AI-UI-16 1315680000遠(yuǎn)程IOUR20-4AO-UI-16 1315170000遠(yuǎn)程IOUR20-4DI-P 1315220000遠(yuǎn)程IOUR20-4DO-P 1315230000遠(yuǎn)程IOUR20-4DO-P-2A 1394420000遠(yuǎn)程IOUR20-4DO-PN-2A 1315550000遠(yuǎn)程IOUR20-4RO-CO-255 1315540000遠(yuǎn)程IOUR20-4RO-SSR-255 1315180000遠(yuǎn)程IOUR20-8DI-P-2W 1394400000遠(yuǎn)程IOUR20-8DI-P-3W 1315240000遠(yuǎn)程IOUR20-8DO-P 1334910000遠(yuǎn)程IOUR20-FBC-EC 1334920000遠(yuǎn)程IOUR20-FBC-EIP 1334710000遠(yuǎn)程IOUR20-PF-I 1334740000遠(yuǎn)程IOUR20-PF-O 1469340000遠(yuǎn)程IOUR20-PG0.35 1334790000遠(yuǎn)程IOUR20-16AUX-FE 1334800000遠(yuǎn)程IOUR20-16AUX-GND-I 1334810000遠(yuǎn)程IOUR20-16AUX-GND-O 1508080000遠(yuǎn)程IOUR20-2FCNT-100 1315600000遠(yuǎn)程IOUR20-2PWM-PN-0.5A 1315690000遠(yuǎn)程IOUR20-4AI-UI-16-DIAG 1315730000遠(yuǎn)程IOUR20-4AO-UI-16-DIAG 1315190000遠(yuǎn)程IOUR20-8DI-P-3W-HD 1315770000遠(yuǎn)程IOUR20-ES 1335030000遠(yuǎn)程IOUR20-PF-O-1DI-SIL 1335040000遠(yuǎn)程IOUR20-PF-O-2DI-DELAY-SIL 1335050000遠(yuǎn)程IOUR20-PF-O-2DI-SIL 2453880000遠(yuǎn)程UR20-4AO-UI-16-M 2476450000遠(yuǎn)程UR20-FBC-MOD-TCP-V2 。
131558 遠(yuǎn)程I/O UR20-1CNT-500魏德米勒模塊
所謂的模塊導(dǎo)入,是指在一個(gè)模塊中使用另一個(gè)模塊的代碼的操作,它有利于代碼的復(fù)用。也許你看到這個(gè)標(biāo)題,會(huì)說我怎么會(huì)發(fā)這么基礎(chǔ)的文章。與此相反。恰恰我覺得這篇文章的內(nèi)容可以算是Python的進(jìn)階技能,會(huì)深入地探討并以真實(shí)案例講解PythonimportHook的知識(shí)點(diǎn)。當(dāng)然為了使文章更系統(tǒng)全面,前面會(huì)有小篇幅講解基礎(chǔ)知識(shí)點(diǎn),但請(qǐng)你有耐心的往后讀下去,因?yàn)楹竺娌攀潜酒恼碌木A所在,希望你不要錯(cuò)過。.導(dǎo)入系統(tǒng)的基礎(chǔ).導(dǎo)入單元構(gòu)成導(dǎo)入單元有多種,可以是模塊包及變量等。對(duì)于這些基礎(chǔ)的概念,對(duì)于新手還是有必要介紹一下它們的區(qū)別。模塊類似.py,.pyc,.pyd,.so,.dll這樣的文件,是Python代碼載體的最小單元。包還可以細(xì)分為兩種Regularpackages是一個(gè)帶有__init__.py文件的文件夾,此文件夾下可包含其他子包,或者模塊Namespacepackages關(guān)于Namespacepackages,有的人會(huì)比較陌生,我這里摘抄官方文檔的一段說明來解釋一下。Namespacepackages是由多個(gè)部分構(gòu)成的,每個(gè)部分為父包增加一個(gè)子包。各個(gè)部分可能處于文件系統(tǒng)的不同位置。部分也可能處于zip文件中網(wǎng)絡(luò)上,或者Python在導(dǎo)入期間可以搜索的其他地方。命名空間包并不一定會(huì)直接對(duì)應(yīng)到文件系統(tǒng)中的對(duì)象;它們有可能是無實(shí)體表示的虛擬模塊。命名空間包的__path__屬性不使用普通的列表。而是使用定制的可迭代類型,如果其父包的路徑或者最高層級(jí)包的sys.path發(fā)生改變,這種對(duì)象會(huì)在該包內(nèi)的下一次導(dǎo)入嘗試時(shí)自動(dòng)執(zhí)行新的對(duì)包部分的搜索。命名空間包沒有parent/__init__.py文件。實(shí)際上,在導(dǎo)入搜索期間可能找到多個(gè)parent目錄,每個(gè)都由不同的部分所提供。因此parent/one的物理位置不一定與parent/two相鄰。在這種情況下,Python將為頂級(jí)的parent包創(chuàng)建一個(gè)命名空間包,無論是它本身還是它的某個(gè)子包被導(dǎo)入。.相對(duì)/絕對(duì)對(duì)導(dǎo)入當(dāng)我們import導(dǎo)入模塊或包時(shí),Python提供兩種導(dǎo)入方式相對(duì)導(dǎo)入relativeimportimportfoo.bar或者bfooimportbar絕對(duì)導(dǎo)入absoluteimportfrom.importB或from..AimportB,其中.表示當(dāng)前模塊,..表示上層模塊你可以根據(jù)實(shí)際需要進(jìn)行選擇,但有必要說明的是,在早期的版本Python.之前,Python默認(rèn)使用的相對(duì)導(dǎo)入。而后來的版本中Python.之后,都以絕對(duì)導(dǎo)入為默認(rèn)使用的導(dǎo)入方式。使用絕對(duì)路徑和相對(duì)路徑各有利弊當(dāng)你在開發(fā)維護(hù)自己的項(xiàng)目時(shí),應(yīng)當(dāng)使用相對(duì)路徑導(dǎo)入,這樣可以避免硬編碼帶來的麻煩。而使用絕對(duì)路徑,會(huì)讓你模塊導(dǎo)入結(jié)構(gòu)更加清晰,而且也避免了重名的包沖突而導(dǎo)入錯(cuò)誤。.導(dǎo)入的標(biāo)準(zhǔn)寫法在PEP中有一條,對(duì)模塊的導(dǎo)入順序提出了要求,不同來源模塊導(dǎo)入,應(yīng)該有清晰的界限,使用一空行來分開。import語句應(yīng)當(dāng)分行書寫#badimportos,sys#goodimportosimportsysimport語句應(yīng)當(dāng)使用absoluteimport#badfrom..barimportBar#goodfromfoo.barimporttestimport語句應(yīng)當(dāng)放在文件頭部,置于模塊說明及docb之后,全局變量之前import語句應(yīng)該按照順序排列,每組之間用一個(gè)空格分隔,按照內(nèi)置模塊,第三方模塊,自己所寫的模塊調(diào)用順序,同時(shí)每組內(nèi)部按照字母表順序排列#內(nèi)置模塊importosimportsys#第三方模塊importflask#本地模塊fromfooimportbar.__import__的妙用在Python中使用import關(guān)鍵字來實(shí)現(xiàn)模塊/包的導(dǎo)入,可以說是基礎(chǔ)中的基礎(chǔ)。但這不是唯一的方法,還有importlib.import_module和__import__等。對(duì)于__import__,普通的開發(fā)者,可能就會(huì)比較陌生。和import不同的是,__import__是一個(gè)函數(shù),也正是因?yàn)檫@個(gè)原因,使得__import__的使用會(huì)更加靈活,常常用于框架中,對(duì)于插件的動(dòng)態(tài)加載。實(shí)際上,當(dāng)我們調(diào)用import導(dǎo)入模塊時(shí),其內(nèi)部也是調(diào)用了__import__,請(qǐng)看如下兩種導(dǎo)入方法,他們是等價(jià)的。#使用importimportos#使用__import__os=__import__'os'通過舉一反三,下面兩種方法同樣也是等價(jià)的。#使用import..as..importpandasaspd#使用__import__pd=__import__'pandas'上面我說__import__常常用于插件的動(dòng)態(tài),事實(shí)上也只有它能做到相對(duì)于import來說。插件通常會(huì)位于某一特定的文件夾下,在使用過程中,可能你并不會(huì)用到全部的插件,也可能你會(huì)新增插件。如果使用import關(guān)鍵字這種硬編碼的方式,顯然太不優(yōu)雅了,當(dāng)你要新增/修改插件的時(shí)候,都需要你修改代碼。更合適的做法是,將這些插件以配置的方式,寫在配置文件中,然后由代碼去讀取你的配置,動(dòng)態(tài)導(dǎo)入你要使用的插件,即靈活又方便,也不容易出錯(cuò)。假如我的一個(gè)項(xiàng)目中,有plugin0plugin0plugin0plugin0四個(gè)插件,這些插件下都會(huì)實(shí)現(xiàn)一個(gè)核心方法run。但有時(shí)候我不想使用全部的插件,只想使用plugin0plugin0,那我就在配置文件中寫我要使用的兩個(gè)插件。#my.confcustom_plugins=['plugin0','plugin0']那我如何使用動(dòng)態(tài)加載,并運(yùn)行他們呢。#main.pyforplugininconf.custom_plugins__import__pluginsys.modules[plugin].run.理解模塊的緩存在一個(gè)模塊內(nèi)部重復(fù)引用另一個(gè)相同模塊,實(shí)際并不會(huì)導(dǎo)入兩次,原因是在使用關(guān)鍵字import導(dǎo)入模塊時(shí),它會(huì)先檢索sys.modules里是否已經(jīng)載入這個(gè)模塊了,如果已經(jīng)載入,則不會(huì)再次導(dǎo)入,如果不存在,才會(huì)去檢索導(dǎo)入這個(gè)模塊。來實(shí)驗(yàn)一下,在my_mod0這個(gè)模塊里,我import兩次my_mod0這個(gè)模塊,按邏輯每一次import會(huì)一次my_mod0里的代碼即打印inmod0,但是驗(yàn)證結(jié)果是,只打印了一次。$catmy_mod0.pyprint'inmod0'$catmy_mod0.pyimportmy_mod0importmy_mod0$pythonmy_mod0.pyinmod0該現(xiàn)象的解釋是因?yàn)橛衧ys.modules的存在。sys.modules是一個(gè)字典key模塊名,value模塊對(duì)象,它存放著在當(dāng)前namespace所有已經(jīng)導(dǎo)入的模塊對(duì)象。#test_module.pyimportsysprintsys.modules.get'json','NotFound'importjsonprintsys.modules.get'json','NotFound'運(yùn)行結(jié)果如下,可見在導(dǎo)入后json模塊后,sys.modules才有了json模塊的對(duì)象。$pythontest_module.pyNotFoundmodule'json'from'C\Python\lib\json\__init__.pyc'由于有緩存的存在,使得我們無法重新載入一個(gè)模塊。但若你想反其道行之,可以借助importlib這個(gè)神奇的庫來實(shí)現(xiàn)。事實(shí)也確實(shí)有此場(chǎng)景,比如在代碼調(diào)試中,在發(fā)現(xiàn)代碼有異常并修改后,我們通常要重啟服務(wù)再次載入程序。這時(shí)候,若有了模塊重載,就無比方便了,修改完代碼后也無需服務(wù)的重啟,就能繼續(xù)調(diào)試。還是以上面的例子來理解,my_mod0.py改寫成如下#my_mod0.pyimportimportlibimportmy_mod0importlib.reloadmy_mod0使用python來執(zhí)行這個(gè)模塊,與上面不同的是,這邊執(zhí)行了兩次my_mod0.py$pythonmy_mod0.pyinmod0inmod0.查找器與加載器如果指定名稱的模塊在sys.modules找不到,則將發(fā)起調(diào)用Python的導(dǎo)入?yún)f(xié)議以查找和加載該模塊。此協(xié)議由兩個(gè)概念性模塊構(gòu)成,即查找器和加載器。一個(gè)Python的模塊的導(dǎo)入,其實(shí)可以再細(xì)分為兩個(gè)過程由查找器實(shí)現(xiàn)的模塊查找由加載器實(shí)現(xiàn)的模塊加載.查找器是什么。查找器finder,簡(jiǎn)單點(diǎn)說,查找器定義了一個(gè)模塊查找機(jī)制,讓程序知道該如何找到對(duì)應(yīng)的模塊。其實(shí)Python內(nèi)置了多個(gè)默認(rèn)查找器,其存在于sys.b_path中。但這些查找器對(duì)應(yīng)使用者來說,并不是那么重要,因此在Python.之前,Python解釋將其隱藏了,我們稱之為隱式查找器。#Python.importsyssys.b_path由于這點(diǎn)不利于開發(fā)者深入理解import機(jī)制,在Python.后,所有的模塊導(dǎo)入機(jī)制都會(huì)通過sys.b_path暴露,不會(huì)在有任何隱式導(dǎo)入機(jī)制。#Python.importsyssys.b_path[class'_frozen_importlib.BuiltinImporter',class'_frozen_importlib.FrozenImporter',class'_frozen_importlib_external.PathFinder',class'_frozen_importlib_external.PathFinder']觀察一下Python默認(rèn)的這幾種查找器finder,可以分為三種一種知道如何導(dǎo)入內(nèi)置模塊一種知道如何導(dǎo)入凍結(jié)模塊一種知道如何導(dǎo)入來自importpath的模塊即pathbasedfinder。那我們能不能自已定義一個(gè)查找器呢。當(dāng)然可以,你只要定義一個(gè)實(shí)現(xiàn)了find_module方法的類py和py均可,或者實(shí)現(xiàn)find_loader類方法僅py有效,如果找到模塊需要返回一個(gè)loader對(duì)象或者M(jìn)oduleSpec對(duì)象后面會(huì)講,沒找到需要返回None定義完后,要使用這個(gè)查找器,必須注冊(cè)它,將其插入在sys.b_path的首位,這樣就能優(yōu)先使用。importsysclassMyFinderb@classbdeffind_modulecls,name,path,target=NoneprintImporting,name,path,target#將在后面定義returnMyLoader#由于finder是按順序讀取的,所以必須插入在首位sys.b_path.insert0,MyFinder查找器可以分為兩種b+--Finderdeprecated+--MetaPathFinder+--PathEntryFinder這里需要注意的是,在.版前,查找器會(huì)直接返回加載器Loader對(duì)象,而在.版后,查找器則會(huì)返回模塊規(guī)格說明ModuleSpec,其中包含加載器。而關(guān)于什么是加載器和模塊規(guī)格說明,請(qǐng)繼續(xù)往后看。.加載器是什么。查找器只負(fù)責(zé)查找定位找模,而真正負(fù)責(zé)加載模塊的,是加載器loader。一般的loader必須定義名為load_module的方法。為什么這里說一般,因?yàn)閘oader還分多種b+--Finderdeprecated|+--MetaPathFinder|+--PathEntryFinder+--Loader+--ResourceLoader--------++--InspectLoader|+--ExecutionLoader--++--FileLoader+--SourceLoader通過查看源碼可知,不同的加載器的抽象方法各有不同。加載器通常由一個(gè)查找器返回。詳情參見PEP0。那如何自定義我們自己的加載器呢。你只要定義一個(gè)實(shí)現(xiàn)了load_module方法的類對(duì)與導(dǎo)入有關(guān)的屬性點(diǎn)擊查看詳情進(jìn)行校驗(yàn)創(chuàng)建模塊對(duì)象并綁定所有與導(dǎo)入相關(guān)的屬性變量到該模塊上將此模塊保存到sys.modules中順序很重要,避免遞歸導(dǎo)入然后加載模塊這是核心若加載出錯(cuò),需要能夠處理拋出異常ImportError,若加載成功,則返回module對(duì)象若你想看具體的例子,可以接著往后看。.模塊的規(guī)格說明導(dǎo)入機(jī)制在導(dǎo)入期間會(huì)使用有關(guān)每個(gè)模塊的多種信息,特別是加載之前。大多數(shù)信息都是所有模塊通用的。模塊規(guī)格說明的目的是基于每個(gè)模塊來封裝這些導(dǎo)入相關(guān)信息。模塊的規(guī)格說明會(huì)作為模塊對(duì)象的__spec__屬性對(duì)外公開。有關(guān)模塊規(guī)格的詳細(xì)內(nèi)容請(qǐng)參閱ModuleSpec。在Python.后,查找器不再返回加載器,而是返回ModuleSpec對(duì)象,它儲(chǔ)存著更多的信息模塊名加載器模塊絕對(duì)路徑那如何查看一個(gè)模塊的ModuleSpec。這邊舉個(gè)例子$catmy_mod0.pyimportmy_mod0printmy_mod0.__spec__$pythonmy_mod0.pyinmod0ModuleSpecname='my_mod0',loader=_frozen_importlib_external.SourceFileLoaderbat0x000000000DBE0,origin='/home/MING/my_mod0.py'從ModuleSpec中可以看到,加載器是包含在內(nèi)的,那我們?nèi)绻匦录虞d一個(gè)模塊,是不是又有了另一種思路了。來一起驗(yàn)證一下?,F(xiàn)在有兩個(gè)文件一個(gè)是my_info.py#my_info.pyname='python'另一個(gè)是main.py#main.pyimportmy_infoprintmy_info.name#加一個(gè)斷點(diǎn)importpdb。pdb.set_trace#再加載一次my_info.__spec__.loader.load_moduleprintmy_info.name在main.py處,我加了一個(gè)斷點(diǎn),目的是當(dāng)運(yùn)行到斷點(diǎn)處時(shí),我修改my_info.py里的name為ming,以便驗(yàn)證重載是否有效。$pythonmain.pypython/home/MING/main.pymodule-my_info.__spec__.loader.load_modulePdbcming從結(jié)果來看,重載是有效的。.導(dǎo)入器是什么。導(dǎo)入器importer,也許你在其他文章里會(huì)見到它,但其實(shí)它并不是個(gè)新鮮的東西。它只是同時(shí)實(shí)現(xiàn)了查找器和加載器兩種接口的對(duì)象,所以你可以說導(dǎo)入器importer是查找器finder,也可以說它是加載器loader。.遠(yuǎn)程導(dǎo)入模塊由于Python默認(rèn)的查找器和加載器僅支持本地的模塊的導(dǎo)入,并不支持實(shí)現(xiàn)遠(yuǎn)程模塊的導(dǎo)入。為了讓你更好的理解PythonImportHook機(jī)制,我下面會(huì)通過實(shí)例演示,如何自己實(shí)現(xiàn)遠(yuǎn)程導(dǎo)入模塊的導(dǎo)入器。.動(dòng)手實(shí)現(xiàn)導(dǎo)入器當(dāng)導(dǎo)入一個(gè)包的時(shí)候,Python解釋器首先會(huì)從sys.b_path中拿到查找器列表。默認(rèn)順序是內(nèi)建模塊查找器-凍結(jié)模塊查找器-第三方模塊路徑本地的sys.path查找器若經(jīng)過這三個(gè)查找器,仍然無法查找到所需的模塊,則會(huì)拋出ImportError異常。因此要實(shí)現(xiàn)遠(yuǎn)程導(dǎo)入模塊,有兩種思路。一種是實(shí)現(xiàn)自己的元路徑導(dǎo)入器;另一種是編寫一個(gè)鉤子,添加到sys.path_hooks里,識(shí)別特定的目錄命名模式。我這里選擇第一種方法來做為示例。實(shí)現(xiàn)導(dǎo)入器,我們需要分別查找器和加載器。首先是查找器由源碼得知,路徑查找器分為兩種MetaPathFinderPathEntryFinder這里使用MetaPathFinder來進(jìn)行查找器的編寫。在Python.版本之前,查找器必須實(shí)現(xiàn)find_module方法,而Python.+版,則推薦使用find_spec方法,但這并不意味著你不能使用find_module,但是在沒有find_spec方法時(shí),導(dǎo)入?yún)f(xié)議還是會(huì)嘗試find_module方法。我先舉例下使用find_module該如何寫。fromimportlibimportabcclassUrlMetaFinderabc.MetaPathFinderdef__init__self,basebself._baseb=basebdeffind_moduleself,fullname,path=NoneifpathisNonebaseb=self._basebelse#不是原定義的b就直接返回不存在ifnotpath.startswithself._basebreturnNonebaseb=pathtryloader=UrlMetaLoaderbaseb#loader.load_modulefullnameexceptExceptionreturnNone若使用find_spec,要注意此方法的調(diào)用需要帶有兩到三個(gè)參數(shù)。第一個(gè)是被導(dǎo)入模塊的完整限定名稱,例如foo.bar.baz。第二個(gè)參數(shù)是供模塊搜索使用的路徑條目。對(duì)于最高層級(jí)模塊,第二個(gè)參數(shù)為None,但對(duì)于子模塊或子包,第二個(gè)參數(shù)為父包__path__屬性的值。如果相應(yīng)的__path__屬性無法訪問,將引發(fā)ModuleNotFoundError。第三個(gè)參數(shù)是一個(gè)將被作為稍后加載目標(biāo)的現(xiàn)有模塊對(duì)象。導(dǎo)入系統(tǒng)僅會(huì)在重加載期間傳入一個(gè)目標(biāo)模塊。fromimportlibimportabcfromimportlib.machineryimportModuleSpecclassUrlMetaFinderabc.MetaPathFinderdef__init__self,basebself._baseb=basebdeffind_specself,fullname,path=None,target=NoneifpathisNonebaseb=self._basebelse#不是原定義的b就直接返回不存在ifnotpath.startswithself._basebreturnNonebaseb=pathtryloader=UrlMetaLoaderbasebreturnModuleSpecfullname,loader,is_package=loader.is_packagefullnameexceptExceptionreturnNone接下來是加載器由源碼得知,路徑查找器分為兩種FileLoaderSourceLoader按理說,兩種加載器都可以實(shí)現(xiàn)我們想要的功能,我這里選用SourceLoader來示范。在SourceLoader這個(gè)抽象類里,有幾個(gè)很重要的方法,在你寫實(shí)現(xiàn)加載器的時(shí)候需要注意get_code獲取源代碼,可以根據(jù)自己場(chǎng)景實(shí)現(xiàn)實(shí)現(xiàn)。exec_module執(zhí)行源代碼,并將變量賦值給module.dictget_data抽象方法,必須實(shí)現(xiàn),返回指定路徑的字節(jié)碼。get_filename抽象方法,必須實(shí)現(xiàn),返回文件名在一些老的博客文章中,你會(huì)經(jīng)??吹郊虞d器要實(shí)現(xiàn)load_module,而這個(gè)方法早已在Python.的時(shí)候就被廢棄了,當(dāng)然為了兼容考慮,你若使用load_module也是可以的。fromimportlibimportabcclassUrlMetaLoaderabc.SourceLoaderdef__init__self,basebself.baseb=basebdefget_codeself,fullnamef=blib.bopenself.get_filenamefullnamereturnf.readdefload_moduleself,fullnamecode=self.get_codefullnamemod=sys.modules.setdefaultfullname,imp.new_modulefullnamemod.__file__=self.get_filenamefullnamemod.__loader__=selfmod.__package__=fullnameexeccode,mod.__dict__returnNonedefget_dataselfpassdefexecute_moduleself,modulepassdefget_filenameself,fullnamereturnself.baseb+fullname+'.py'當(dāng)你使用這種舊模式實(shí)現(xiàn)自己的加載時(shí),你需要注意兩點(diǎn),很重要execute_module必須重載,而且不應(yīng)該有任何邏輯,即使它并不是抽象方法。load_module,需要你在查找器里手動(dòng)執(zhí)行,才能實(shí)現(xiàn)模塊的加載做為替換,你應(yīng)該使用execute_module和create_module。由于基類里已經(jīng)實(shí)現(xiàn)了execute_module和create_module,并且滿足我們的使用場(chǎng)景。我這邊可以不用重復(fù)實(shí)現(xiàn)。和舊模式相比,這里也不需要在設(shè)查找器里手動(dòng)執(zhí)行execute_module。importblib.requestasblibclassUrlMetaLoaderimportlib.abc.SourceLoaderdef__init__self,basebself.baseb=basebdefget_codeself,fullnamef=blib.bopenself.get_filenamefullnamereturnf.readdefget_dataselfpassdefget_filenameself,fullnamereturnself.baseb+fullname+'.py'查找器和加載器都有了,別忘了往sys.b_path注冊(cè)我們自定義的查找器UrlMetaFinder。definstall_baddressfinder=UrlMetaFinderaddresssys.b_path.appendfinder所有的代碼都解析完畢后,我們將其整理在一個(gè)模塊my_importer.py中#my_importer.pyimportsysimportimportlibimportblib.requestasblibclassUrlMetaFinderimportlib.abc.MetaPathFinderdef__init__self,basebself._baseb=basebdeffind_moduleself,fullname,path=NoneifpathisNonebaseb=self._basebelse#不是原定義的b就直接返回不存在ifnotpath.startswithself._basebreturnNonebaseb=pathtryloader=UrlMetaLoaderbasebexceptExceptionreturnNoneclassUrlMetaLoaderimportlib.abc.SourceLoaderdef__init__self,basebself.baseb=basebdefget_codeself,fullnamef=blib.bopenself.get_filenamefullnamereturnf.readdefget_dataselfpassdefget_filenameself,fullnamereturnself.baseb+fullname+'.py'definstall_baddressfinder=UrlMetaFinderaddresssys.b_path.appendfinder.搭建遠(yuǎn)程服務(wù)端最開始我說了,要實(shí)現(xiàn)一個(gè)遠(yuǎn)程導(dǎo)入模塊的方法。我還缺一個(gè)在遠(yuǎn)端的服務(wù)器,來存放我的模塊,為了方便,我使用python自帶的http.server模塊用一條命令即可實(shí)現(xiàn)。$mkdirhttpservercdhttpserver$catmy_info.pyEOFname='Python編程時(shí)光'print'ok'EOF$catmy_info.pyname='Python編程時(shí)光'print'ok'$$python-mhttp.server00ServingHTTPon0.0.0.0port00......一切準(zhǔn)備好,我們就可以驗(yàn)證了。frommy_importerimportinstall_binstall_b'#往sys.b_path注冊(cè)finderimportmy_info#打印ok,說明導(dǎo)入成功okmy_info.name#驗(yàn)證可以取得到變量'Python編程時(shí)光'至此,我實(shí)現(xiàn)了一個(gè)簡(jiǎn)易的可以導(dǎo)入遠(yuǎn)程服務(wù)器上的模塊的導(dǎo)入器。.參考文檔.//docs.python.org/zh-cn//library/importlib.html#module-importlib.abc.。
131558 遠(yuǎn)程I/O UR20-1CNT-500魏德米勒模塊
133477 遠(yuǎn)程IO UR20-16AUX-I魏德米勒模塊:http://qqppn.cn/jdzjnews/k3_15729853.html