python 導(dǎo)入自定義包-引包機(jī)制

[[toc]]

前言

在學(xué)習(xí)unittest框架時(shí)發(fā)現(xiàn),在IDE(pycharm)上可以正常運(yùn)行腳本,但在CMD中運(yùn)行腳本時(shí),出現(xiàn)了錯誤,無法運(yùn)行,提示“引包錯誤”。通過查找資料,找到了答案,現(xiàn)在總結(jié)一下:獲取絕對路徑,python引包機(jī)制

一、在pycharm運(yùn)行正常,在命令行窗口出現(xiàn)引包錯誤,怎么辦?

在出現(xiàn)錯誤的那個(gè)py文件,找到需要引入的包錯誤的工程路徑,然后sys.path.insert(相應(yīng)的路徑),如:

image.png

我在2包中調(diào)用1包中的first.py里面的函數(shù)hello(),在 pycharm運(yùn)行正常,但是在命令行運(yùn)行出錯

Traceback(most recent call last):
??File "second.py", line8, in <module>
??????from first import hello
ModuleNotFoundError: No module named 'first'

這時(shí)候只需要在second.py文件上,在最上面添加這個(gè)代碼:


import os

import sys

dir_mytest = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

sys.path.insert(0, dir_mytest)

from first import hello

這里為什么要這么做呢?是因?yàn)橐话鉏DE都會自動的匹配好相關(guān)的環(huán)境路徑,故在IDE中運(yùn)行沒問題。但在cmd命令行中就會出現(xiàn)“引包錯誤”的問題,故在腳本中,我們通常都要把絕對路徑插入到os.path中。

有點(diǎn)要注意的是:python3是向下機(jī)制的。所以插入路徑的代碼要放在引包代碼之前

二、python 獲取當(dāng)前絕對路徑

在使用python的時(shí)候總會遇到路徑切換的使用情況,如想從文件夾test下的test.py調(diào)用data文件夾下的data.txt文件:


.

└── folder

    ├── data

    │  └── data.txt

    └── test

        └── test.py

  • 一種方法可以在data文件下加入init.py 然后在test.py 中import data 就可以調(diào)用data.txt文件;

  • 另一種方法可以獲取絕對路徑加入到os.path中

而獲取絕對路徑的方法有多種:

方法一


import os

# 獲取當(dāng)前目錄絕對路徑

dir_path = os.path.dirname(os.path.abspath(__file__))

print('當(dāng)前目錄絕對路徑:', dir_path)

# 獲取上級目錄絕對路徑

dir_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

print('上級目錄絕對路徑:', dir_path)

運(yùn)行結(jié)果:


當(dāng)前目錄絕對路徑: D:\mytest\mytest\abspath

上級目錄絕對路徑: D:\mytest\mytest

方法二


import os

import sys

dir_path = os.path.abspath(os.path.split(__file__)[0])

print('當(dāng)前目錄絕對路徑:', dir_path)

# 獲取上級目錄絕對路徑

dir_path = os.path.abspath(os.path.split(os.path.split(__file__)[0])[0])

print('上級目錄絕對路徑:', dir_path)

運(yùn)行結(jié)果:


當(dāng)前目錄絕對路徑: D:\mytest\mytest\abspath

上級目錄絕對路徑: D:\mytest\mytest

方法三


import os

print('***獲取當(dāng)前目錄***')

print(os.getcwd())

print('***獲取上級目錄***')

print(os.path.abspath(os.path.join(os.getcwd(), "..")))

print('***獲取上上級目錄***')

print(os.path.abspath(os.path.join(os.getcwd(), "../..")))

運(yùn)行結(jié)果:


***獲取當(dāng)前目錄***

D:\mytest\mytest\abspath

***獲取上級目錄***

D:\mytest\mytest

***獲取上上級目錄*** __粗體__

D:\mytest

三、python 引包機(jī)制

python中,每個(gè)py文件被稱之為模塊,每個(gè)具有_init_.py文件的目錄被稱為包。只要模塊或者包所在的目錄在sys.path中,就可以使用import 模塊或import 包來使用。

如果想使用非當(dāng)前模塊中的代碼,需要使用Import,這個(gè)大家都知道。

如果你要使用的模塊(py文件)和當(dāng)前模塊在同一目錄,只要import相應(yīng)的文件名就好,比如在a.py中使用b.py:


import b

但是如果要import一個(gè)不同目錄的文件(例如b.py)該怎么做呢?
首先需要使用sys.path.insert()方法將b.py所在目錄加入到搜素目錄中。然后進(jìn)行import即可。

python在執(zhí)行import語句時(shí),到底進(jìn)行了什么操作,按照python的文檔,它執(zhí)行了如下操作:

第1步,創(chuàng)建一個(gè)新的,空的module對象(它可能包含多個(gè)module);
第2步,把這個(gè)module對象插入sys.module中
第3步,裝載module的代碼(如果需要,首先必須編譯)
第4步,執(zhí)行新的module中對應(yīng)的代碼。

在執(zhí)行第3步時(shí),首先要找到module程序所在的位置,其原理為:

如 果需要導(dǎo)入的module的名字是m1,則解釋器必須找到m1.py,它首先在當(dāng)前目錄查找,然后是在環(huán)境變量PYTHONPATH中查找。 PYTHONPATH可以視為系統(tǒng)的PATH變量一類的東西,其中包含若干個(gè)目錄。如果PYTHONPATH沒有設(shè)定,或者找不到m1.py,則繼續(xù)搜索 與python的安裝設(shè)置相關(guān)的默認(rèn)路徑

事實(shí)上,搜索的順序是:

當(dāng)前路徑 (以及從當(dāng)前目錄指定的sys.path),然后是PYTHONPATH,然后是python的安裝設(shè)置相關(guān)的默認(rèn)路徑。正因?yàn)榇嬖谶@樣的順序,如果當(dāng)前 路徑或PYTHONPATH中存在與標(biāo)準(zhǔn)module同樣的module,則會覆蓋標(biāo)準(zhǔn)module。也就是說,如果當(dāng)前目錄下存在xml.py,那么執(zhí) 行import xml時(shí),導(dǎo)入的是當(dāng)前目錄下的module,而不是系統(tǒng)標(biāo)準(zhǔn)的xml。

包機(jī)制
a.py文件:


# a.py

def add_func(a,b):

    return a+b

b.py文件:


# b.py

from a import add_func

print ("Result of 1 plus 2 is: ")

print (add_func(1,2))   

模塊(module)可以定義在包里面。Python定義包的方式稍微有點(diǎn)古怪,假設(shè)我們有一個(gè)parent文件夾,該文件夾有一個(gè)child子文件夾。child中有一個(gè)模塊(module) a.py , 如何讓Python知道這個(gè)文件層次結(jié)構(gòu)?很簡單,每個(gè)目錄都放一個(gè)名為init.py 的文件,該文件內(nèi)容可以為空,這個(gè)層次結(jié)構(gòu)如下所示:

parent

--_init.py

--child

-- __init_.py

--a.py

那么Python如何找到我們定義的module?在標(biāo)準(zhǔn)包sys中,path屬性記錄了Python的包路徑。你可以將之打印出來:


import sys

print(sys.path)

通常我們可以將module的包路徑放到環(huán)境變量PYTHONPATH中,該環(huán)境變量會自動添加到sys.path屬性。另一種方便的方法是編程中直接指定我們的module路徑到sys.path 中:


import sys

import os

dir_mytest = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

sys.path.insert(0, dir_mytest)

from a import add_func

print (sys.path)

print ("Result of 1 plus 2 is: ")

print (add_func(1,2))

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 模塊和包 一 模塊 1 什么是模塊? 常見的場景:一個(gè)模塊就是一個(gè)包含了python定義和聲明的文件,文件名就是...
    go以恒閱讀 2,348評論 0 4
  • 當(dāng)前目錄 和 腳本目錄 參考資料:https://techibee.com/python/get-current-...
    ThomasYoungK閱讀 11,876評論 0 11
  • 一、Python簡介和環(huán)境搭建以及pip的安裝 4課時(shí)實(shí)驗(yàn)課主要內(nèi)容 【Python簡介】: Python 是一個(gè)...
    _小老虎_閱讀 6,338評論 0 10
  • If you quit from the Python interpreter and enter it agai...
    linyk3閱讀 461評論 0 0
  • 認(rèn)識李先生是因?yàn)橄嘤H。 那天,他穿一條卡其色褲子,黑T。忽然對這人有了好感,因?yàn)?/div>
    九月C閱讀 312評論 0 0

友情鏈接更多精彩內(nèi)容