網(wǎng)站首頁 編程語言 正文
一、包
在我們的項目中,可能會有太多的模塊
但是我們不能把所有的模塊這樣放在這里,這樣項目會亂七八糟。
我們可以將所有相同類型的模塊放在一個文件夾中,這個文件夾就叫做包
包就是文件夾,他用于存放文件也就是模塊。包中也可以存放包
包就是一個包含了__init__.py文件的文件夾。
包只是模塊的一種形式而已,包即模塊。
包的結(jié)構:
包
|----__init__.py 包的標志文件
|----模塊一
|----模塊二
|----子包(文件夾)
|----|----__init__.py
|----|----子模塊一
|----|----子模塊二
二、包的導入
1.關于包相關的導入語句也分為import和from ... import ...兩種,但是無論哪種,無論在什么位置,在導入時都必須遵循一個原則:凡是在導入時帶點的,點的左邊都必須是一個包,否則非法。可以帶有一連串的點,如demo0demo02.demo03,但都必須遵循這個原則。
2.對于導入后,在使用時就沒有這種限制了,點的左邊可以是包,模塊,函數(shù),類(它們都可以用點的方式調(diào)用自己的屬性)。
3.對比import demo和from demo import name的應用場景:
如果我們想直接使用name那必須使用后者。
1.import 導入
在demo01_test02.py 中 導入 demo01_test01.py
demo01_test01.py 源碼:
def say():
print('demo01_test01_hello')
name = '趙四'
demo01_test02.py 源碼:
import base.demo01.demo01_test01
base.demo01.demo01_test01.say() # 調(diào)用test01中的say方法 輸出 demo01_test01_hello
import sys
print(sys.path)
#['D:\\pycharm工作空間\\day12\\base\\demo01', 'D:\\pycharm工作空間\\day12', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\python36.zip', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\DLLs', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages\\win32', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages\\win32\\lib', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages\\Pythonwin', 'C:\\Program Files\\JetBrains\\PyCharm 2018.3.2\\helpers\\pycharm_matplotlib_backend']
2.from...import...導入
from 包名.模塊名... import 變量名
使用方式: 例如 變量名() 或者print(變量名)
demo01_test02.py 源碼:
from base.demo01.demo01_test01 import say
say() # demo01_test01_hello
from 包名.模塊名... import 變量名1,變量名2,...
使用方式: 例如 變量名1() 或者print(變量名2)
demo01_test02.py 源碼:
from base.demo01.demo01_test01 import say,name
say()
print(name) # 調(diào)用test01中的name變量
from 包名 import 模塊名
使用方式:模塊名.變量名() 或者 print(模塊名.變量名)
demo01_test02.py 源碼:
from base.demo01 import demo01_test01
demo01_test01.say() # demo01_test01_hello
from 包名 import 模塊名,模塊名1...
使用方式:模塊名.變量名() 或者 print(模塊名1.變量名)
在demo01_test02.py中調(diào)用demo02_test01.py,?demo02_test02.py 源碼
demo02_test01.py 源碼:
def say21():
print('demo02_test01_hello')
?demo02_test02.py 源碼:
def say22():
print('demo02_test02_hello')
demo01_test02.py 源碼:
from base.demo02 import demo02_test01,demo02_test02
demo02_test01.say21() # demo02_test01_hello
demo02_test02.say22() # demo02_test02_hello
需要注意的是from后import導入的模塊,必須是明確的一個不能帶點,否則會有語法錯誤,如:from a import b.c是錯誤語法?
from base.demo02 import demo02_test02.say
# 報錯 SyntaxError: invalid syntax
3.__init__.py文件
不管是哪種方式,只要是第一次導入包或者是包的任何其他部分,都會依次執(zhí)行包下的__init__.py文件(我們可以在每個包的文件內(nèi)都打印一行內(nèi)容來驗證一下),這個文件可以為空,但是也可以存放一些初始化包的代碼。
demo1下的__init__.py文件源碼:
print('啦啦啦')
demo01_test02.py 源碼:
from base.demo01 import demo01_test01
demo01_test01.say()
# 啦啦啦 __init__.py中的代碼執(zhí)行結(jié)果
# demo01_test01_hello
4.from 包.模塊 import *
此處是想從包demo02中導入所有,實際上該語句只會導入包demo02下__init__.py文件中定義的名字,我們可以在這個文件中定義__all___:
demo02下__init__.py文件的源碼:
print('嗚嗚嗚')
name = '王大夫'
?demo01_test02.py 源碼:
from base.demo02 import *
print(name) # 王大夫
demo02_test01.say() # 報錯 無法調(diào)用
# 輸出: 嗚嗚嗚
# NameError: name 'demo02_test01' is not defined
在demo02下的__init__.py文件中加入以下源碼:
print('嗚嗚嗚')
name = '王大夫'
__all__ = ['demo02_test01','demo02_test02']
再調(diào)用:
from base.demo02 import *
demo02_test01.say21() # 成功調(diào)用
print(name) # 報錯 變量name沒有定義
# 嗚嗚嗚
# demo02_test01_hello
三、包的相對和絕對導入
我們的最頂級包base是寫給別人用的,然后在base包內(nèi)部也會有彼此之間互相導入的需求,這時候就有絕對導入和相對導入兩種方式:
絕對導入:以base作為起始
相對導入:用.或者..的方式最為起始(只能在一個包中使用,不能用于不同目錄內(nèi))
1. 絕對導入
在demo01中的demo01_test02.py中調(diào)用demo02中的模塊
from base.demo01 import demo01_test01
demo01_test01.say()
在 base目錄下的py文件中調(diào)用demo01_test02.py
from base.demo01 import demo01_test02
demo01_test02.demo01_test01.say()
2.相對導入
在demo01中的demo01_test02.py中調(diào)用demo02中的模塊
from ..demo02.demo02_test01 import say21
say21()
在 base目錄下的py文件中調(diào)用demo01_test02.py?
from base.demo01 import demo01_test02
demo01_test02.say21()
import sys
print(sys.path)
'''
啦啦啦
嗚嗚嗚
demo02_test01_hello
demo02_test01_hello
['D:\\pycharm工作空間\\day12\\base', 'D:\\pycharm工作空間\\day12', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\python36.zip', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\DLLs', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages\\win32', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages\\win32\\lib', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages\\Pythonwin', 'C:\\Program Files\\JetBrains\\PyCharm 2018.3.2\\helpers\\pycharm_matplotlib_backend']
'''
相對路徑運行注意事項:
在沒有明確指定包結(jié)構的情況下,Python 是根據(jù) __name__ 來決定一個模塊在包中的結(jié)構的,如果是 __main__ 則它本身是頂層模塊,沒有包結(jié)構,如果是base.demo01.demo02 結(jié)構,那么頂層模塊是 base。
如果是相對導入,一個模塊必須有包結(jié)構且只能導入它的頂層模塊內(nèi)部的模塊
如果一個模塊被直接運行,則它自己為頂層模塊,不存在層次結(jié)構,所以找不到其他的相對路徑。
?四、import 導入自定義包的子模塊
特別需要注意的是:可以用import導入內(nèi)置或者第三方模塊(已經(jīng)在sys.path中),但是要絕對避免使用import來導入自定義包的子模塊(沒有在sys.path中),應該使用from... import ...的絕對或者相對導入。
demo03中的test01源碼:
def test():
print('這是一個測試方法')
直接運行demo03_test02模塊
import test01
test01.test()
import sys
print(sys.path)
'''這是一個測試方法
['D:\\pycharm工作空間\\day12\\base\\demo03', 'D:\\pycharm工作空間\\day12', 'D:\\pycharm工作空間\\day12\\base\\demo03', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\python36.zip', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\DLLs', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages\\win32', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages\\win32\\lib', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages\\Pythonwin', 'C:\\Program Files\\JetBrains\\PyCharm 2018.3.2\\helpers\\pycharm_matplotlib_backend']
'''
不會報錯因為sys.path中已經(jīng)添加了day05-包/demo03路徑。Import會從sys.path中依次搜索路徑。
在base目錄下導入demo03_test02.py進行使用
from base.demo03 import test02
# 報錯 ModuleNotFoundError: No module named 'test01'
因為此時的sys.path中只有demo01-包.py的路徑 .../day05-包,import demo03_test01 只能從/day05-包下查找 demo03_test01模塊。找不到因此報錯。?
解決import 導入包時的報錯問題
我們可以在sys.path中添加import搜索的路徑。
import sys,os
path = os.path.abspath(__file__)
print(path)
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
print(BASE_DIR)
sys.path.append(BASE_DIR)
print(sys.path)
import base.demo03.test01
base.demo03.test01.test() # 這是一個測試方法
五、包的單獨導入
單獨導入包名稱時不會導入包中所有包含的所有子模塊
import base.demo03
base.demo03.test01.test()
# 報錯 AttributeError: module 'base.demo03' has no attribute 'test01'
解決辦法:需要從__init__.py中進行初始化操作?
進行上訴操作后:
六、包的安裝和發(fā)布
1、在包的同級目錄創(chuàng)建 setup.py
from distutils.core import setup
setup(name='bag',
version='1.0,3',
description='描述:這是我的第一個包',
author='zxb',
author_email='505555162@qq.com',
py_modules=['test1', 'test2'],
)
2.在命令行 運行 python setup.py build (可以不執(zhí)行 )?
構建模塊??
?
4.生成發(fā)布的壓縮包 運行 python setup.py sdist
5、安裝包
導入自己的包進行測試
測試成功??!
包的卸載: 直接找到對應的位置刪除即可。
總結(jié)
原文鏈接:https://blog.csdn.net/weixin_42223833/article/details/86168012
相關推薦
- 2021-12-15 C#?多線程學習之基礎入門_C#教程
- 2022-10-03 Observing?KVO?Key-Value基本使用原理示例詳解_IOS
- 2022-08-19 Linux系統(tǒng)文件目錄介紹
- 2022-10-21 Go語言基于HTTP的內(nèi)存緩存服務的實現(xiàn)_Golang
- 2022-03-29 詳解C++?的STL迭代器原理和實現(xiàn)_C 語言
- 2022-05-21 k8s入門集群組件介紹及概念理解_服務器其它
- 2021-12-13 linux壓縮文件和文件解壓縮命令介紹_Linux
- 2022-11-08 H5頁面 禁止微信分享轉(zhuǎn)發(fā)按鈕
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支