python文件間模塊調(diào)用

? ? ? ? 一般項目中模塊一般會分布在文件系統(tǒng)的不同路徑中析苫。Python解釋器找到某個模塊并將其導(dǎo)入命名空間會遵循一定的搜索規(guī)則兜叨,這個規(guī)則就是模塊路徑搜索順序。

模塊路徑搜索

python搜索模塊的路徑順序:

1)衩侥、程序運行的工作目錄

2)国旷、PTYHONPATH目錄(如果已經(jīng)進行了設(shè)置)

3)、標(biāo)準(zhǔn)連接庫目錄(linux下一般在/usr/local/lib/python2.X/)

4)茫死、任何的.pth文件的內(nèi)容(如果存在的話).新功能跪但,允許用戶把有效果的目錄添加到模塊搜索路徑中去,.pth后綴的文本文件中一行一行的地列出目錄峦萎。

這四個組合起來就變成了sys.path了屡久。sys.path是python的搜索模塊的路徑集,是一個list爱榔,如

>>> importsys

>>>sys.path

['','/usr/lib64/python27.zip', '/usr/lib64/python2.7','/usr/lib64/python2.7/plat-linux2', '/usr/lib64/python2.7/lib-tk','/usr/lib64/python2.7/lib-old', '/usr/lib64/python2.7/lib-dynload','/root/.local/lib/python2.7/site-packages', '/usr/lib64/python2.7/site-packages','/usr/lib64/python2.7/site-packages/gtk-2.0','/usr/lib/python2.7/site-packages']

>>>?

? ? ? ? ? 因此只要模塊或者包所在的目錄在sys.path中被环,就可以使用import 模塊或import 包命令格式來使用。下面以如下一個文件結(jié)構(gòu)為例

[root@localhostpython]# tree

.

├──moduleA.py

├──mylib

?? ├──moduleB_2.py

?? ├──moduleB.py

?? └──sublib

????├──moduleC.py

├──otherlib

?? ├──moduleD.py

└──run.py

同級目錄導(dǎo)入

? ? ? ? ?處于同級目錄的兩個模塊直接使用import?或from 模塊名 import *相互調(diào)用详幽。但這也只限于其中一個模塊文件作為主程序運行筛欢。如在run.py中下列導(dǎo)入是合法的導(dǎo)入

import moduleA

???? 而無法直接導(dǎo)入其他目錄中的模塊,如import moduleB是非法的唇聘。而且指定全路徑也是極其錯誤的版姑,如import?/test/python/mylib/moduleB,這和php不一樣迟郎。

??????? 而且導(dǎo)入過程和python解釋器當(dāng)前工作目錄無關(guān)漠酿,

[root@localhostpython]# python run.py

in moduleA file

in run file

[root@localhostpython]# cd ..

[root@localhosttest]# python python/run.py

in moduleA file

in run file


跨目錄調(diào)用

??? 跨目錄調(diào)用分以下幾種情況

[if !supportLists]????? [endif]主程序所在的目錄是模塊所在目錄的父(或祖輩)目錄

[if !supportLists]????? [endif]主程序?qū)肷蠈幽夸浿械哪K

跨目錄導(dǎo)入有統(tǒng)一的導(dǎo)入模式,可以使用sys.path.append方法將模塊加入到程序搜索路徑中谎亩。如在run.py中導(dǎo)入moduleB.py炒嘲,我們可以這么做

[root@localhostpython]# vi run.py

import sys

sys.path.append('/test/python/mylib')

?

import moduleB

print("in runfile")

再次運行

[root@localhostpython]# python run.py

in moduleB file

in run file

? ? ? 使用這種方法有兩個缺點宇姚,一是在退出python環(huán)境后自己添加的路徑就會自動消失了,且它是在實踐中極為脆弱夫凸,應(yīng)盡量避免使用纠亚;二是它將目錄名硬編碼到了你的源代碼昵骤。如果你的代碼被移到一個新的位置,這會導(dǎo)致維護問題。

? ? ? 為了解決這些問題甲捏,可以有以下兩個方法。

? ? ? ?使用PYTHONPATH環(huán)境變量來添加污呼。在自定義應(yīng)用程序中歧胁,這樣的環(huán)境變量可在程序啟動時設(shè)置或通過shell 腳本。如shell中桶现,

[root@localhost python]# export PYTHONPATH=/usr/lib/

[root@localhost python]# python

Python 2.7.5 (default, Apr? 92019, 14:30:50)

[GCC 4.8.5 20150623 (Red Hat 4.8.5-36)] on linux2

Type "help", "copyright", "credits" or"license" for more information.

>>> import sys

>>> sys.path

['', '/usr/lib','/usr/lib64/python27.zip', '/usr/lib64/python2.7','/usr/lib64/python2.7/plat-linux2', '/usr/lib64/python2.7/lib-tk','/usr/lib64/python2.7/lib-old', '/usr/lib64/python2.7/lib-dynload','/root/.local/lib/python2.7/site-packages','/usr/lib64/python2.7/site-packages','/usr/lib64/python2.7/site-packages/gtk-2.0','/usr/lib/python2.7/site-packages']

>>>?

? ? ? ? 上述操作只針對當(dāng)前窗口生效躲雅,我們可以vi /etc/profile,在最后添加 export PYTHONPATH=/usr/lib/對所有用戶生效骡和。

? ? ? ? ?使用.pth文件相赁,在site-packages 文件中創(chuàng)建 .pth文件,將模塊的路徑寫進去慰于,一行一個路徑钮科。site-packages目錄是第三方包和模塊安裝的目錄。如果你手動安裝你的代碼婆赠,它將被安裝到site-packages目錄绵脯。雖然用于配置path的.pth 文件必須放置在site-packages里,但它配置的路徑可以是系統(tǒng)上任何你希望的目錄休里。因此蛆挫,你可以把你的代碼放在一系列不同的目錄,只要那些目錄包含在.pth 文件里份帐。

???????? 除了上述方法外璃吧,還可以將模塊封裝成包,見下節(jié)废境。

python中畜挨,每個py文件被稱之為模塊,而每個包含有__init__.py文件的目錄或文件夾被稱為包噩凹。在創(chuàng)建許許多多模塊后巴元,我們可能希望將某些功能相近的文件組織在同一文件夾下,在這個文件夾下再增加一個?__init__.py文件驮宴,這個文件夾就成為了包逮刨。即包是python模塊文件所在的目錄,且該目錄下必須存在__init__.py文件。典型的包結(jié)構(gòu)如下:

package

├── __init__.py

├── module_a.py

└── module_b.py

? ? ? ? ? 最簡單的情況下修己,只需要一個空的 __init__.py 文件即可恢总。當(dāng)然它也可以執(zhí)行包的初始化代碼或者設(shè)置__all__值。包下面是一些模塊文件和子目錄睬愤,假如子目錄中也有 __init__.py 那么它就是這個包的子包了片仿。

? ? ? ? 包的使用同模塊一樣,使用 import 尤辱、 from ... import 語句砂豌,來改變命名空間。

__init__.py

??如上所述光督,封裝成包是很簡單的阳距。在文件系統(tǒng)上組織你的代碼,并確保每個目錄都定義了一個__init__.py文件结借。

如在mylib文件夾下新建一個__init__文件筐摘。

[root@localhost mylib]# touch __init__.py

那么mylib目錄現(xiàn)在就是一個包。如果要在run.py中導(dǎo)入moduleB.py模塊映跟,可以寫入如下格式導(dǎo)入moduleB.py

[root@localhost python]# vi run.py

import mylib.moduleB

….

[root@localhost python]# python run.py

in moduleB file

in run file

即導(dǎo)入包中的模塊使用如下格式

pkg1.pkg2.~.pkgn.模塊名

包的導(dǎo)入注意點凡是在導(dǎo)入時帶點的蓄拣,點的左邊都必須是一個包扬虚,否則非法努隙。如果想要導(dǎo)入moduleC.py模塊,還需要在sublib目錄下新建__init__.py文件辜昵。如

[root@localhost sublib]# touch __init__.py

[root@localhost python]#vi run.py

import mylib.sublib.moduleC

[root@localhost python]# python run.py

in moduleC file

in run file

?

?????? 上述導(dǎo)入指明了包的全路徑荸镊,這個路徑(頂層包名)是相對于主程序所在目錄而言的,

[root@localhost mylib]# vi moduleB.py

import otherlib.moduleD?????????????#導(dǎo)入otherlib

import moduleB_2??????????????????#同目錄下的模塊

print("in moduleB file")

?

[root@localhost mylib]# python moduleB.py

Traceback (most recent call last):

? File "moduleB.py",line 1, in

??? import otherlib.moduleD

ImportError: No module named otherlib.moduleD

這是因為moduleB.py所在的mylib目錄下沒有otherlib包堪置。

這也意味著我們在導(dǎo)入模塊的時候躬存,最好寫全包的路徑(從頂層包開始),除非兩個模塊在同一個目錄舀锨,如

[root@localhost python]# vi run.py

import mylib.moduleB?????????????????#導(dǎo)入mylib

print("in run file")

?

[root@localhost python]# python run.py

in moduleD file

in moduleB_2 file

in moduleB file

in run file

?

?????? 它的導(dǎo)入過程是解釋器首先發(fā)現(xiàn)要導(dǎo)入mylib包下的moduleB.py岭洲,于是在該包下找到了moduleB.py,在導(dǎo)入該文件時坎匿,又發(fā)現(xiàn)需要導(dǎo)入otherlib包下的moduleD.py盾剩,于是去otherlib(就在當(dāng)前主程序同目錄下)包下找moduleD.py。

? ? ? ? 以上的用法都是使用了包的全路徑來導(dǎo)入的替蔬。這實際上算是一種絕對路徑告私。使用絕對路徑名的不利之處是這將頂層包名硬編碼到你的源碼中。如果你想重新組織它承桥,你的代碼將更脆驻粟,很難工作。舉個例子凶异,如果你改變了包名蜀撑,你就必須檢查所有文件來修正源碼挤巡。同樣,硬編碼的名稱會使移動代碼變得困難酷麦。

???而相對路徑中玄柏,用. 為當(dāng)前目錄,.. 為父目錄贴铜。但這種方法只適用于from … import的導(dǎo)入方式粪摘。如

[root@localhost python]# vi run.py

import mylib.sublib.moduleC

print("in run file")

[root@localhost sublib]# cat moduleC.py

from .. import moduleB_2

#import mylib.moduleB_2

print("in moduleC file")

?

上述語句即實現(xiàn)在sublib/module.py中導(dǎo)入上層目錄中的moduleB_2.py。

[root@localhost python]# python run.py

in moduleB_2 file

in moduleC file

in run file

注意Relative imports use a module’s name attribute to

determine that module’s position in the package hierarchy. Note that relative imports are based on the name of the current module.

? ? ? ?上述導(dǎo)入的過程是通過import mylib.sublib.moduleC找到moduleC.py文件绍坝,在該文件中徘意,因為有相對導(dǎo)入語句,就以當(dāng)前模塊為參考轩褐,去找父目錄下找moduleB_2.py椎咧,它實際上等價于import

mylib.moduleB_2。

top-levelscript

每一個被直接運行的python

script都會被視作是top-level script把介。top-level

script的__name__被自動設(shè)置成__main__勤讽。那么它所在的目錄將不被python視為包,通過相對導(dǎo)入將不起作用拗踢,如

[root@localhost mylib]# vi moduleB.py

from . import moduleB_2

print("in moduleB file")

?

[root@localhost mylib]# python moduleB.py

Traceback (most recent call last):

? File "moduleB.py",line 3, in

??? from . import moduleB_2

ValueError: Attempted relative import in non-package

?????? moduleB.py所在的目錄現(xiàn)在不是包了脚牍,通過相對導(dǎo)入將不起作用。

再比如

[root@localhost mylib]# vi moduleB.py

import sublib.moduleC

print("in moduleB file")

?

[root@localhost mylib]# cat sublib/moduleC.py

from .. import moduleB_2

print("in moduleC file")

?

[root@localhost mylib]# python moduleB.py

Traceback (most recent call last):

? File "moduleB.py",line 1, in

??? import sublib.moduleC

? File"/test/python/mylib/sublib/moduleC.py", line 1, in

??? from .. import moduleB_2

ValueError: Attempted relative import beyond toplevel package

? 這是因為moduleB.py作為主程序入口巢墅,mylib目錄就不是包了诸狭,而sublib就變成了頂層包。在sublib/moduleC.py中使用相對導(dǎo)入使用父目錄下的模塊當(dāng)然就不會被允許了君纫。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末驯遇,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蓄髓,更是在濱河造成了極大的恐慌叉庐,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件会喝,死亡現(xiàn)場離奇詭異陡叠,居然都是意外死亡,警方通過查閱死者的電腦和手機好乐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門匾竿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蔚万,你說我怎么就攤上這事岭妖。” “怎么了?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵昵慌,是天一觀的道長假夺。 經(jīng)常有香客問我,道長斋攀,這世上最難降的妖魔是什么已卷? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮淳蔼,結(jié)果婚禮上侧蘸,老公的妹妹穿的比我還像新娘。我一直安慰自己鹉梨,他們只是感情好讳癌,可當(dāng)我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著存皂,像睡著了一般晌坤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上旦袋,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天骤菠,我揣著相機與錄音,去河邊找鬼疤孕。 笑死商乎,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的胰柑。 我是一名探鬼主播截亦,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼爬泥,長吁一口氣:“原來是場噩夢啊……” “哼柬讨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起袍啡,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤踩官,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后境输,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蔗牡,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年嗅剖,在試婚紗的時候發(fā)現(xiàn)自己被綠了辩越。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡信粮,死狀恐怖黔攒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤督惰,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布不傅,位于F島的核電站,受9級特大地震影響赏胚,放射性物質(zhì)發(fā)生泄漏访娶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一觉阅、第九天 我趴在偏房一處隱蔽的房頂上張望崖疤。 院中可真熱鬧,春花似錦典勇、人聲如沸戳晌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽沦偎。三九已至,卻和暖如春咳蔚,著一層夾襖步出監(jiān)牢的瞬間豪嚎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工谈火, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留侈询,地道東北人。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓糯耍,卻偏偏與公主長得像扔字,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子温技,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容