本文相關(guān)鏈接:
- Python官網(wǎng)、Python 3.11.5 中文文檔、慕課:Python語言程序設(shè)計(jì)、Real Python :Write More Pythonic Code
- Miniconda、Anaconda、conda文檔
- Python 標(biāo)準(zhǔn)庫官方文檔、 《os — 多種操作系統(tǒng)接口》、《os.path — 常用路徑操作》、《shutil — 高階文件操作》
- Pandas文檔《Input/output》、 openpyxl官方文檔、xlrd官方文檔、json模塊、pickle模塊
七、模塊和包
??在Python中,模塊(Moudle)和包(Package)是組織和管理代碼的重要方式。它們有助于將代碼分割成可管理的塊,提高了代碼的可重用性和可維護(hù)性。現(xiàn)在,讓我們深入了解這兩個(gè)概念。
7.1 模塊
??模塊是一個(gè)包含Python代碼的文件,其文件名是模塊名加后綴名 .py
。文件中可以包含函數(shù)、變量和類,它們被組織在一起以便在其它地方重用。所以我們只需編寫Python代碼并將其保存為.py文件,就創(chuàng)建了一個(gè)模塊,其他程序就可以導(dǎo)入它并使用其中的功能。
??模塊的文件名應(yīng)該是一個(gè)有效的Python標(biāo)識(shí)符,遵循Python的命名約定,不能與Python的關(guān)鍵字或者與標(biāo)準(zhǔn)庫、已安裝的第三方庫重名,防止沖突。最好使用有描述性的變量、函數(shù)和類名,以提高代碼的可讀性。
7.1.1 模塊搜索路徑
??在Python中,要使用模塊或包中的內(nèi)容,您需要導(dǎo)入它們。Python解釋器在導(dǎo)入模塊時(shí)會(huì)搜索模塊的路徑,包括以下位置:
- 當(dāng)前目錄
- Python標(biāo)準(zhǔn)庫的安裝位置
- 環(huán)境變量
PYTHONPATH
中指定的目錄 - Python內(nèi)置的一些默認(rèn)目錄
??這些路徑按照優(yōu)先級(jí)的順序搜索。首先,解釋器會(huì)查找當(dāng)前目錄是否有所需的模塊,然后才會(huì)繼續(xù)搜索其他路徑。如果找到匹配的模塊,解釋器會(huì)導(dǎo)入它。
??標(biāo)準(zhǔn)庫通常安裝在Python的安裝目錄中,而site-packages目錄包含了第三方模塊的安裝位置。運(yùn)行以下代碼,你將看到Python標(biāo)準(zhǔn)庫的安裝位置和site-packages目錄的路徑。
import sys
import site
print("Python標(biāo)準(zhǔn)庫的安裝位置:")
print(sys.prefix)
print("\nPython的site-packages目錄:")
print(site.getsitepackages())
7.1.2 PYTHONPATH
和sys.path
PYTHONPATH
??環(huán)境變量PYTHONPATH
允許您自定義模塊搜索路徑,這對(duì)于在項(xiàng)目中使用自定義模塊或第三方模塊非常有用。你可以使用下面的方式查看和設(shè)置PYTHONPATH
。
-
在Linux或macOS系統(tǒng)上,可以在終端中執(zhí)行
echo $PYTHONPATH
命令來查看PYTHONPATH,使用export PYTHONPATH=/path/to/your/custom/modules
以在PYTHONPATH中指定自定義模塊的搜索路徑。 -
在windows系統(tǒng)中,可以使用Python代碼來訪問和配置PYTHONPATH
import os pythonpath = os.environ.get('PYTHONPATH') if pythonpath: print("PYTHONPATH的值:", pythonpath) else: print("PYTHONPATH未設(shè)置") # 未設(shè)置PYTHONPATH時(shí),其值為None
import os # 設(shè)置PYTHONPATH的值 new_pythonpath = "/path/to/your/custom/modules" os.environ['PYTHONPATH'] = new_pythonpath # 驗(yàn)證是否已成功設(shè)置 pythonpath = os.environ.get('PYTHONPATH') if pythonpath: print("已設(shè)置的PYTHONPATH的值:", pythonpath) else: print("PYTHONPATH未設(shè)置")
上述代碼僅在當(dāng)前Python進(jìn)程中更改了PYTHONPATH的值。如果您希望永久更改系統(tǒng)環(huán)境變量,需要在系統(tǒng)環(huán)境變量中添加。
sys.path
??sys.path
是一個(gè)包含目錄路徑的列表,Python解釋器在導(dǎo)入模塊時(shí)會(huì)搜索這些路徑。以下是如何使用sys.path
管理模塊搜索路徑的示例:
import sys
# 查看當(dāng)前sys.path的值
print("當(dāng)前sys.path:", sys.path)
# 添加一個(gè)自定義模塊路徑到sys.path
custom_module_path = "/path/to/your/custom/modules"
sys.path.append(custom_module_path)
# 再次查看sys.path,您將看到新路徑已添加
print("更新后的sys.path:", sys.path)
# 現(xiàn)在可以導(dǎo)入自定義模塊
import custom_module
-
sys.path
和PYTHONPATH
的區(qū)別
??sys.path
和 PYTHONPATH
都用于管理 Python 模塊的搜索路徑,但它們之間存在一些重要的區(qū)別:
-
作用范圍:
-
sys.path
是 Python 解釋器級(jí)別的,它僅影響當(dāng)前 Python 進(jìn)程中的模塊搜索路徑。這意味著對(duì)sys.path
的更改僅在當(dāng)前 Python 程序中生效,不會(huì)影響全局環(huán)境或其他 Python 進(jìn)程。 -
PYTHONPATH
是操作系統(tǒng)級(jí)別的環(huán)境變量,它影響所有 Python 進(jìn)程的模塊搜索路徑,包括您在命令行中運(yùn)行的 Python 腳本、Python IDE 中的代碼,以及其他所有 Python 程序。因此,更改PYTHONPATH
可以全局影響 Python 模塊的搜索路徑。
-
-
優(yōu)先級(jí):
-
當(dāng)導(dǎo)入模塊時(shí),
sys.path
中的路徑優(yōu)先于PYTHONPATH
中的路徑。這意味著如果在sys.path
中找到了匹配的模塊,將首先使用它,而不會(huì)查找PYTHONPATH
中的路徑。 -
如果沒有在
sys.path
中找到模塊,Python 解釋器將繼續(xù)查找PYTHONPATH
中的路徑。 -
如果使用了虛擬環(huán)境,虛擬環(huán)境會(huì)自動(dòng)管理
sys.path
,以便在虛擬環(huán)境中安裝的模塊優(yōu)先于全局模塊。這可以確保項(xiàng)目的依賴關(guān)系得到良好的隔離和管理。
-
-
動(dòng)態(tài)性:
-
您可以在運(yùn)行時(shí)使用 Python 代碼修改
sys.path
,以動(dòng)態(tài)添加或刪除模塊搜索路徑,而不需要重新啟動(dòng) Python 進(jìn)程。 -
要更改
PYTHONPATH
,您通常需要重新啟動(dòng)與環(huán)境變量關(guān)聯(lián)的 Python 進(jìn)程,這意味著更改可能需要在啟動(dòng)新進(jìn)程之前生效。
-
-
局部性:
-
sys.path
更適合項(xiàng)目級(jí)別的管理,您可以在項(xiàng)目代碼中使用它來管理模塊搜索路徑,以確保項(xiàng)目的依賴關(guān)系得到良好的隔離。 -
PYTHONPATH
更適合全局配置,用于設(shè)置系統(tǒng)范圍的模塊搜索路徑,可能影響多個(gè)項(xiàng)目和 Python 進(jìn)程。
-
??綜上所述,sys.path
更加靈活,適用于在項(xiàng)目級(jí)別管理模塊搜索路徑,不會(huì)影響全局環(huán)境。而 PYTHONPATH
用于全局配置,影響所有 Python 進(jìn)程。通常情況下,在項(xiàng)目中使用虛擬環(huán)境和 sys.path
更為常見,因?yàn)樗峁┝烁玫母綦x性和控制,這對(duì)于在不同項(xiàng)目中使用不同的模塊版本或自定義模塊非常有用。
7.1.2 模塊的導(dǎo)入和常見錯(cuò)誤
Python提供了不同的模塊導(dǎo)入方式,以滿足不同的需求。
- 使用
import module_name
導(dǎo)入整個(gè)模塊。 - 使用
from module_name import function_name
導(dǎo)入模塊中的特定函數(shù)或變量。 - 使用
as
關(guān)鍵字為模塊或?qū)氲膬?nèi)容創(chuàng)建別名。
示例:
import math # 導(dǎo)入整個(gè)math模塊
result = math.sqrt(25) # 使用模塊中的函數(shù)
from math import sqrt # 導(dǎo)入math模塊中的sqrt函數(shù)
result = sqrt(25) # 可以直接使用函數(shù),不需要模塊前綴
import numpy as np # 導(dǎo)入NumPy庫并為其創(chuàng)建一個(gè)別名
my_array = np.array([1, 2, 3]) # 創(chuàng)建一個(gè)NumPy數(shù)組
除了使用完整的絕對(duì)路徑或模塊名,也可以使用相對(duì)路徑來導(dǎo)入模塊,這分兩種情況:
- 相對(duì)于當(dāng)前模塊的相對(duì)路徑導(dǎo)入: 這種方式允許您在同一目錄中的模塊之間進(jìn)行相對(duì)路徑導(dǎo)入。
假設(shè)你有以下項(xiàng)目結(jié)構(gòu):
my_project/
├── main.py
├── module1.py
└── module2.py
如果你想從 module1.py
中導(dǎo)入 module2.py
,您可以使用相對(duì)路徑導(dǎo)入如下:
# module1.py
from . import module2 # 使用相對(duì)路徑導(dǎo)入
我們一般用
.
表示當(dāng)前目錄,使用..
表示父目錄。
- 相對(duì)于頂級(jí)包的相對(duì)路徑導(dǎo)入
如果您的項(xiàng)目是一個(gè)包(包含一個(gè)__init__.py
文件的目錄),您可以使用相對(duì)于頂級(jí)包的相對(duì)路徑導(dǎo)入。
假設(shè)您有以下項(xiàng)目結(jié)構(gòu):
my_package/
├── __init__.py
├── subpackage/
│ ├── __init__.py
│ ├── module1.py
│ └── module2.py
└── main.py
如果您想從 module1.py
中導(dǎo)入 module2.py
,可以使用相對(duì)路徑導(dǎo)入如下:
# module1.py
from ..subpackage import module2 # 使用相對(duì)路徑導(dǎo)入
??在這個(gè)示例中,..
表示父包(my_package
),然后導(dǎo)入了子包 subpackage
中的 module2.py
。
??需要注意的是,相對(duì)路徑導(dǎo)入通常在包內(nèi)部使用,以便在包內(nèi)的模塊之間進(jìn)行導(dǎo)入,這可以使項(xiàng)目結(jié)構(gòu)更清晰,但需要謹(jǐn)慎使用,以確保相對(duì)路徑的正確性。通常更常見的是使用絕對(duì)路徑導(dǎo)入或直接使用模塊名導(dǎo)入。
7.1.3 模塊的緩存機(jī)制
此部分更多細(xì)節(jié)及決策流程圖,詳見 PEP 3147
??為了快速加載模塊,Python解釋器會(huì)緩存已經(jīng)導(dǎo)入的模塊,避免重復(fù)導(dǎo)入和提高性能。這意味著模塊只會(huì)在第一次導(dǎo)入時(shí)執(zhí)行一次,后續(xù)導(dǎo)入將使用緩存的版本。
??Python 一般把模塊的編譯版本緩存在 __pycache__
目錄中,文件名為 module.version.pyc,其中海報(bào)好了編譯器的版本號(hào),例如CPython 的 3.3 發(fā)行版中,spam.py
的編譯版本緩存為 __pycache__/spam.cpython-33.pyc
。這種命名慣例讓不同 Python 版本編譯的模塊可以共存。
??另外,Python 會(huì)對(duì)比編譯版與源碼的修改日期,查看編譯版是否已過期,是否要重新編譯,此進(jìn)程是完全自動(dòng)的,與平臺(tái)也沒有關(guān)系,因此,Python可在不同架構(gòu)的系統(tǒng)之間共享相同的庫。
7.1.4 __name__
和 __main__
函數(shù)
??__name__
是一個(gè)內(nèi)置的特殊變量,當(dāng)模塊被導(dǎo)入時(shí),__name__
的值是模塊的名稱。但當(dāng)模塊被直接運(yùn)行時(shí),__name__
的值是 "__main__"
,所以它可用于確定模塊是以主程序運(yùn)行還是被導(dǎo)入到其他程序中。
??我們?cè)?code>__main__函數(shù)中編寫的代碼,只有在模塊被直接運(yùn)行時(shí)才執(zhí)行,而在被導(dǎo)入時(shí)不執(zhí)行。假設(shè)我們有一個(gè)名為 my_module.py
的模塊,其中包含以下代碼:
# my_module.py
def my_function():
print("Function called.")
if __name__ == "__main__":
print("This module is run directly as the main program.")
else:
print("This module is imported.")
??現(xiàn)在,如果我們?cè)诹硪粋€(gè)腳本中導(dǎo)入這個(gè)模塊,只會(huì)執(zhí)行 else
分支,因?yàn)榇藭r(shí)__name__
的值是模塊的名稱:
import my_module # 輸出 "This module is imported."
但如果我們直接運(yùn)行這個(gè)模塊, if __name__ == "__main__":
,會(huì)執(zhí)行其下的代碼塊:
python my_module.py # 輸出 "This module is run directly as the main program."
這使得我們可以在模塊中包含一些用于測(cè)試或執(zhí)行的代碼,而不必?fù)?dān)心它們會(huì)在導(dǎo)入時(shí)執(zhí)行。
7.2 標(biāo)準(zhǔn)庫
詳見Python 標(biāo)準(zhǔn)庫官方文檔
??庫是一組相關(guān)的模塊的集合,通常具有特定的領(lǐng)域或功能。庫也可以稱為包。標(biāo)準(zhǔn)庫(Standard Library)是Python內(nèi)置的一組模塊和功能,Python生態(tài)系統(tǒng)的核心部分。這些模塊和功能提供了各種常見任務(wù)和操作的標(biāo)準(zhǔn)解決方案。Windows 版本的 Python 安裝程序通常包含整個(gè)標(biāo)準(zhǔn)庫,往往還包含許多額外組件。詳情請(qǐng)參考官方文檔。
7.3 包
??包是一個(gè)包含多個(gè)模塊的目錄。它允許將相關(guān)的模塊組織在一起,形成一個(gè)層次結(jié)構(gòu)。包有助于更好地組織大型項(xiàng)目的代碼。它們還可以避免命名沖突,因?yàn)槊總€(gè)包內(nèi)的模塊都有自己的命名空間。
7.3.1 創(chuàng)建包
??創(chuàng)建包只需創(chuàng)建一個(gè)包含__init__.py
文件的目錄,并在其中放置模塊文件。這個(gè)__init__.py
文件可以為空,但它表明這是一個(gè)包。下面詳細(xì)介紹一下 __init__.py
文件的作用。
-
標(biāo)識(shí)一個(gè)目錄作為包
如果你希望將一個(gè)目錄視為Python的包(package),那么這個(gè)目錄中必須包含一個(gè)名為
__init__.py
的文件,Python會(huì)根據(jù)這個(gè)文件來判斷這個(gè)目錄是否應(yīng)該被當(dāng)作一個(gè)包來處理。 -
防止出現(xiàn)目錄名稱與模塊名稱沖突的情況。
例如,如果沒有
__init__.py
文件,Python可能會(huì)將一個(gè)名為string
的目錄誤認(rèn)為是一個(gè)包,從而導(dǎo)致后續(xù)搜索模塊時(shí)出現(xiàn)問題。 -
初始化包的某些功能
__init__.py
也可以包含Python代碼,這可以是在導(dǎo)入包時(shí)自動(dòng)執(zhí)行的初始化代碼,或者定義包的公共接口。例如,你可以設(shè)置特殊變量__all__
,它主要用于控制模塊的公共接口,指定在使用from package import *
語句時(shí),一個(gè)模塊或包中哪些屬性、函數(shù)、類等應(yīng)該被導(dǎo)入到其他模塊中。以下是關(guān)于__all__
的詳細(xì)介紹:
-
作用:
-
__all__
的作用是限制通過from module import *
語句導(dǎo)入的內(nèi)容,以避免導(dǎo)入不需要的標(biāo)識(shí)符,同時(shí)允許開發(fā)者明確指定哪些標(biāo)識(shí)符應(yīng)該是模塊的公共接口。
-
-
使用方式:
-
__all__
是一個(gè)包含字符串的列表(List),其中的每個(gè)字符串都是模塊內(nèi)部定義的標(biāo)識(shí)符的名稱。 -
在一個(gè)模塊的頂層,你可以定義
__all__
變量, 這將明確指定了在from module import *
語句中可以被導(dǎo)入的標(biāo)識(shí)符。假設(shè)有一個(gè)模塊my_module.py
包含以下內(nèi)容:def public_function(): pass def _private_function(): pass class PublicClass: pass class _PrivateClass: pass __all__ = ['public_function', 'PublicClass']
-
如果使用
from my_module import *
語句,只有public_function
和PublicClass
會(huì)被導(dǎo)入,而_private_function
和_PrivateClass
不會(huì)被導(dǎo)入。 -
如果使用
from my_module import _private_function
,則可以導(dǎo)入_private_function
,因?yàn)樗?__all__
中沒有被列出。
-
-
注意事項(xiàng):
-
__all__
不是Python的強(qiáng)制性規(guī)定,而是一種約定。它主要用于指導(dǎo)其他開發(fā)者使用模塊時(shí)應(yīng)該導(dǎo)入哪些內(nèi)容。 -
單下劃線
_
開頭的標(biāo)識(shí)符通常被認(rèn)為是私有的,不應(yīng)該被直接導(dǎo)入,但仍然可以在需要的情況下導(dǎo)入。
-
??總之,__all__
是一種用于控制模塊或包公共接口的方式,它有助于提高代碼的可維護(hù)性和可讀性,同時(shí)避免導(dǎo)入不必要的標(biāo)識(shí)符。
7.3.2 導(dǎo)入包
??我們同樣使用import語句,并指定包名和模塊名來導(dǎo)入包中的模塊。包可以形成層次結(jié)構(gòu),即包含子包和子包下的模塊,只需指定完整的路徑,也可以完成導(dǎo)入。一個(gè)常見的項(xiàng)目結(jié)構(gòu)可能如下所示:
my_project/
├── __init__.py
├── module1.py
├── module2.py
└── subpackage/
├── __init__.py
├── submodule1.py
└── submodule2.py
# module1.py
from ..subpackage import module2 # 使用相對(duì)路徑導(dǎo)入
??在實(shí)際使用中,盡量避免使用 from module import *
,最好是明確導(dǎo)入需要的標(biāo)識(shí)符,例如 from module import func1, class1
,因?yàn)檫@會(huì)產(chǎn)生兩個(gè)問題:
-
污染命名空間(Namespace Pollution):
- 當(dāng)你使用
from module import *
時(shí),Python會(huì)將該模塊中的所有標(biāo)識(shí)符都導(dǎo)入到當(dāng)前的命名空間中,包括模塊中可能沒有被明確設(shè)計(jì)為公共接口的標(biāo)識(shí)符。這意味著你的命名空間會(huì)變得非常擁擠,充斥著許多你可能并不需要的標(biāo)識(shí)符,即命名空間污染。 - 這些額外的標(biāo)識(shí)符可能會(huì)與你的代碼中已經(jīng)定義的標(biāo)識(shí)符產(chǎn)生沖突,導(dǎo)致不可預(yù)測(cè)的行為或錯(cuò)誤。
- 當(dāng)你使用
-
代碼難以理解:
- 當(dāng)你在代碼中看到大量的
from module import *
語句時(shí),很難確定哪些標(biāo)識(shí)符實(shí)際上是來自于這個(gè)模塊,因?yàn)樗鼈儾]有明確地被列出。這會(huì)使代碼變得難以理解和維護(hù),因?yàn)槟銦o法快速識(shí)別哪些標(biāo)識(shí)符來自哪個(gè)模塊。 - 同時(shí),如果你使用了多個(gè) from module import * 語句,不同模塊中的標(biāo)識(shí)符可能會(huì)相互覆蓋,進(jìn)一步增加了混亂和錯(cuò)誤的可能性。
- 當(dāng)你在代碼中看到大量的
7.3.3 pip包管理器
??pip是Python包管理器,專用于安裝、升級(jí)和管理Python包。以下是常用的pip命令:
pip命令 | 描述 |
---|---|
pip --version |
驗(yàn)證pip是否安裝并顯示版本號(hào) |
pip list |
列出已安裝的所有包及其版本號(hào) |
pip install --upgrade pip |
升級(jí)pip到最新版本 |
pip install package_name |
安裝包 |
pip install package_name==desired_version |
安裝特定版本的包 |
pip install --upgrade package_name |
升級(jí)指定包 |
pip uninstall package_name |
卸載指定包 |
pip freeze > requirements.txt |
將當(dāng)前環(huán)境的包列表保存到requirements.txt文件中 |
pip install -r requirements.txt |
從requirements文件安裝所有依賴項(xiàng) |
pip show package_name |
顯示指定包的詳細(xì)信息,包括版本和安裝路徑 |
虛擬環(huán)境相關(guān)命令 | 描述 |
---|---|
pip install virtualenv |
安裝虛擬環(huán)境模塊(如果需要的話) |
python -m venv myenv |
創(chuàng)建新的虛擬環(huán)境(myenv是虛擬環(huán)境的名稱) |
myenv\Scripts\activate (Windows) |
激活虛擬環(huán)境(Windows上) |
source myenv/bin/activate (macOS和Linux) |
激活虛擬環(huán)境(macOS和Linux上) |
deactivate |
退出虛擬環(huán)境 |
其它命令(不常用) | 描述 |
---|---|
pip check |
檢查當(dāng)前環(huán)境的包是否存在問題 |
pip search query |
搜索包含指定關(guān)鍵字的包 |
pip download package_name |
下載指定包的源代碼,但不安裝 |
pip install --user package_name |
在用戶級(jí)別安裝包,而不是全局或虛擬環(huán)境 |
pip install --no-cache-dir package_name |
安裝包時(shí)禁用緩存,用于解決一些安裝問題 |
7.3.4 conda
Miniconda、Anaconda、conda文檔
??venv 是 Python 的標(biāo)準(zhǔn)庫中自帶的虛擬環(huán)境管理工具,只包含與 Python 環(huán)境相關(guān)的必要組件。這使得它適合于創(chuàng)建純粹的 Python 環(huán)境,即不支持非Python語言的包。所以目前一般是使用conda來管理虛擬環(huán)境。
??conda 是一個(gè)跨平臺(tái)的虛擬環(huán)境管理器,不僅支持 Python,還支持其他編程語言,也可以管理系統(tǒng)依賴項(xiàng),目前有兩個(gè)版本——Miniconda和Anaconda。前者只有幾百M(fèi),是最小化版本,只包括Conda和Python,用戶可以自定義需要安裝的其它包。而后者有5、6G,預(yù)裝了許多包,適用于各種數(shù)據(jù)科學(xué)任務(wù)。
以下是一些常用的conda命令:
conda包管理命令 | 描述 |
---|---|
conda create --name myenv python=3.8 |
創(chuàng)建名為myenv的虛擬環(huán)境,指定python版本為3.8 |
conda activate myenv source activate myenv
|
激活虛擬環(huán)境(windows) 激活虛擬環(huán)境(macOS和Linux) |
conda install package_name |
在激活的虛擬環(huán)境中安裝Python包 |
conda list |
列出當(dāng)前虛擬環(huán)境中已安裝的包 |
conda deactivate |
停用當(dāng)前虛擬環(huán)境 |
conda env export > environment.yml |
導(dǎo)出當(dāng)前虛擬環(huán)境的配置到一個(gè)YAML文件 |
conda env create -f environment.yml |
根據(jù)YAML文件創(chuàng)建虛擬環(huán)境 |
conda remove --name myenv --all |
刪除指定名稱的虛擬環(huán)境及其所有包 |
conda search package_name |
搜索可用于安裝的包 |
conda update --all |
升級(jí)當(dāng)前虛擬環(huán)境中的所有包 |
conda虛擬環(huán)境管理命令 | 描述 |
---|---|
conda update conda |
升級(jí)conda本身 |
conda config --show |
顯示conda的配置信息 |
conda env list |
列出所有已創(chuàng)建的虛擬環(huán)境 |
conda info --env |
顯示當(dāng)前虛擬環(huán)境的詳細(xì)信息 |
conda config --set auto_activate_base false |
禁用默認(rèn)激活基礎(chǔ)環(huán)境(默認(rèn)情況下會(huì)自動(dòng)激活基礎(chǔ)環(huán)境) |
conda config --set auto_activate your_env_name |
設(shè)置your_env_name為默認(rèn)的激活環(huán)境 |
??默認(rèn)情況下,conda自動(dòng)激活base環(huán)境為當(dāng)前使用環(huán)境。如果要更改某個(gè)環(huán)境為默認(rèn)激活環(huán)境,你需要進(jìn)行一下操作:
conda config --set auto_activate_base false # 禁用默認(rèn)激活基礎(chǔ)環(huán)境
conda config --set auto_activate your_env_name # 設(shè)置your_env_name為默認(rèn)的激活環(huán)境
如果要恢復(fù)默認(rèn)激活base環(huán)境,需要運(yùn)行:
conda config --set auto_activate_base true # 恢復(fù)默認(rèn)激活base環(huán)境
7.4 如何組織和管理大型項(xiàng)目中的模塊與包
7.4.1 最佳實(shí)踐
??在大型項(xiàng)目中,組織和管理模塊與包是非常重要的,它有助于代碼的可維護(hù)性和可擴(kuò)展性。以下是一些最佳實(shí)踐:
1. 項(xiàng)目結(jié)構(gòu):
- 使用包(即包含
__init__.py
文件的目錄)來組織相關(guān)的模塊。包可以將相關(guān)模塊放在一起,形成層次結(jié)構(gòu),使代碼更有結(jié)構(gòu)性。
2. 模塊和包的命名:
- 給模塊和包起一個(gè)清晰、有意義的名稱,遵循Python的命名約定。避免使用與Python內(nèi)置模塊或庫相同的名稱,以防止命名沖突。
- 使用有描述性的變量、函數(shù)和類名,以提高代碼的可讀性。
3. 文檔:
- 為模塊、函數(shù)和類編寫文檔字符串(docstrings)。文檔字符串應(yīng)解釋模塊或代碼的用途、輸入?yún)?shù)、返回值等信息。這有助于其他開發(fā)人員理解和使用您的代碼。
- 使用工具如Sphinx來生成文檔,以便更輕松地維護(hù)和分享文檔。
- 維護(hù)更新的文檔,包括項(xiàng)目的使用方法、配置和安裝說明。
文檔字符串的說明可參考《python3.11教程1》4.6章
# numpy.py
"""
NumPy is the fundamental package for scientific computing in Python.
It provides support for arrays, mathematical functions, linear algebra, and more.
For more information, visit: https://numpy.org
"""
import numpy as np
def create_array(shape, dtype=float):
"""
Create a new array of the given shape and data type.
Parameters:
shape (tuple): The shape of the array.
dtype (type): The data type of the elements in the array (default is float).
Returns:
ndarray: A new NumPy array.
"""
return np.zeros(shape, dtype=dtype)
4. 版本控制:
Git官方文檔、Git中文教程、Atlassian Git教程
- 盡量避免模塊之間的循環(huán)依賴。循環(huán)依賴可能導(dǎo)致難以調(diào)試和維護(hù)的問題。
- 使用版本控制系統(tǒng)(如Git)來跟蹤和管理代碼的變化。這有助于團(tuán)隊(duì)合作、版本控制和錯(cuò)誤修復(fù)。
- 使用合適的版本號(hào)管理約定(如Semantic Versioning)來管理您的項(xiàng)目的版本。
5. 自動(dòng)化構(gòu)建和測(cè)試:
- pytest官方文檔、W3Cschool《pytest教程》、realpython網(wǎng)教程《Effective Python Testing With Pytest》
- bilibili視頻 及 視頻博客——pytest 框架
- 編寫單元測(cè)試來驗(yàn)證模塊和函數(shù)的正確性。這有助于捕獲潛在的錯(cuò)誤,并確保代碼在修改后仍然正常工作。
- 使用測(cè)試框架(如unittest或pytest)來自動(dòng)運(yùn)行測(cè)試。
6. 依賴管理:
- 使用依賴管理工具(如pip或conda)來管理項(xiàng)目的依賴關(guān)系。這有助于確保項(xiàng)目在不同環(huán)境中的一致性。
- 使用虛擬環(huán)境來隔離不同項(xiàng)目的依賴,確保項(xiàng)目使用的庫與其他項(xiàng)目不會(huì)發(fā)生沖突。
7. 可擴(kuò)展性和性能優(yōu)化:
- 在設(shè)計(jì)項(xiàng)目時(shí),考慮性能和可擴(kuò)展性。選擇適當(dāng)?shù)臄?shù)據(jù)結(jié)構(gòu)和算法,以便項(xiàng)目能夠在處理大量數(shù)據(jù)時(shí)保持高效。
8. 團(tuán)隊(duì)協(xié)作:
- 如果您在團(tuán)隊(duì)中工作,請(qǐng)遵循共同的編碼約定和工作流程。使用代碼審查來確保代碼質(zhì)量。
7.4.2 Sphinx
??Sphinx 是一個(gè)用于生成文檔的工具,特別是用于編寫和發(fā)布Python項(xiàng)目的文檔。它是一個(gè)強(qiáng)大的文檔生成器,支持多種輸出格式,包括HTML、PDF、ePub等,以及集成了自動(dòng)化的構(gòu)建工具。Sphinx 最初由Python社區(qū)創(chuàng)建,但現(xiàn)在已廣泛用于其他編程語言和項(xiàng)目的文檔生成。以下是 Sphinx 的一些主要特點(diǎn)和用途:
-
結(jié)構(gòu)化文檔:Sphinx 使用一種稱為reStructuredText(或簡稱 reST)的標(biāo)記語言,允許您編寫結(jié)構(gòu)化的文檔。這使得文檔易于閱讀、維護(hù)和版本控制。
-
自動(dòng)索引:Sphinx 可以自動(dòng)生成文檔的索引、目錄和交叉引用,使用戶能夠輕松導(dǎo)航文檔。
-
多種輸出格式:Sphinx 支持多種輸出格式,包括HTML、PDF、ePub、man頁、LaTeX等。
-
擴(kuò)展性:Sphinx 具有豐富的擴(kuò)展和插件系統(tǒng),允許您自定義文檔生成的過程,添加自定義樣式和功能。
-
集成版本控制:Sphinx 可以與版本控制系統(tǒng)(如Git)集成,使您能夠輕松將文檔與代碼同步,以確保文檔的實(shí)時(shí)性。
-
支持多語言:Sphinx 支持多語言文檔,允許您為不同的受眾創(chuàng)建多語言版本的文檔。
-
應(yīng)用廣泛:Sphinx 在許多開源項(xiàng)目中廣泛使用,包括Python自身的官方文檔、Django、numpy、pandas等。
??總的來說,Sphinx 是一個(gè)功能強(qiáng)大的文檔生成工具,特別適用于編寫和發(fā)布Python項(xiàng)目的文檔。它的靈活性和豐富的功能使其成為開發(fā)者、項(xiàng)目維護(hù)者和技術(shù)作者的首選工具之一。以下是一些關(guān)于如何使用 Sphinx 的具體教程、博客和示例項(xiàng)目:
-
Sphinx 官方文檔
Sphinx 的官方文檔是使用 Sphinx 編寫的,它包含了完整的 Sphinx 使用指南。這是開始使用 Sphinx 的最佳起點(diǎn)。
-
Real Python Course: Documenting Python Projects With Sphinx and Read the Docs
在本視頻系列中,將使用 Sphinx ( Python 的實(shí)際標(biāo)準(zhǔn))從頭開始創(chuàng)建項(xiàng)目文檔、將代碼存儲(chǔ)庫連接到 Read The Docs,以自動(dòng)生成和發(fā)布代碼文檔。
-
The Sphinx Book
這是一本關(guān)于如何使用 Sphinx 編寫書籍和長篇文檔的免費(fèi)在線書籍。它提供了詳細(xì)的步驟和示例。
-
Sphinx Gallery
Sphinx Gallery 是一個(gè)示例項(xiàng)目,展示了如何使用 Sphinx 來創(chuàng)建一個(gè)包含代碼示例、文檔和說明的畫廊。這對(duì)于展示您的代碼如何工作非常有用。
八、 I/O系統(tǒng)(文件管理)
8.1 I/O簡介
??文件輸入和輸出,通常縮寫為文件I/O,是計(jì)算機(jī)編程中一個(gè)重要的概念。它涉及到將數(shù)據(jù)從程序讀取到文件(輸入)或從文件寫入到程序(輸出)。文件I/O對(duì)于存儲(chǔ)和檢索數(shù)據(jù)以及與外部世界進(jìn)行交互非常關(guān)鍵。
文件I/O對(duì)于許多任務(wù)至關(guān)重要,例如:
-
數(shù)據(jù)持久性: 文件是一種持久性存儲(chǔ)方法,可以將數(shù)據(jù)保存在磁盤上,以便在程序重新運(yùn)行時(shí)保留數(shù)據(jù)。
-
數(shù)據(jù)共享: 文件允許不同的程序或多個(gè)實(shí)例之間共享數(shù)據(jù)。多個(gè)程序可以讀取和寫入同一個(gè)文件。
-
數(shù)據(jù)備份: 文件允許您創(chuàng)建數(shù)據(jù)的備份,以防數(shù)據(jù)丟失或損壞。
-
外部數(shù)據(jù)交換: 您可以使用文件I/O將數(shù)據(jù)與其他應(yīng)用程序或系統(tǒng)進(jìn)行交換。這在數(shù)據(jù)導(dǎo)入和導(dǎo)出時(shí)非常有用。
-
記錄日志: 許多應(yīng)用程序使用文件來記錄日志信息,以幫助故障排除和監(jiān)視應(yīng)用程序的運(yùn)行情況。
以下是一些基本的文件I/O操作:
-
使用
open()
函數(shù)打開文件。 -
使用
.read()
方法從文件中讀取數(shù)據(jù)。 -
使用
.write()
方法將數(shù)據(jù)寫入文件。 -
使用
with
語句來自動(dòng)關(guān)閉文件,以確保資源的正確管理。
8.2 讀寫文本、二進(jìn)制文件
官方文檔:open函數(shù)、 with 上下文管理器
對(duì)于文本或二進(jìn)制文件,我們可以使用open、read和write函數(shù)來進(jìn)行讀寫,下面是一個(gè)簡單的示例:
# 打開一個(gè)文本文件以供寫入
with open("example.txt", "w") as file:
file.write("這是一個(gè)示例文本。")
8.2.1 open函數(shù)
open函數(shù)常用于打開文件,其語法為:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
常用參數(shù)解析:
-
file
(必需):這是要打開的文件的名稱(包括路徑),可以是相對(duì)路徑或絕對(duì)路徑。如果文件不存在,根據(jù)所選的模式來操作。 -
mode
(可選):這是文件打開的模式,它表示您要對(duì)文件執(zhí)行的操作。默認(rèn)是只讀模式(‘r’)。
模式 | 描述 |
---|---|
'r' |
只讀模式,文件只能被讀?。J(rèn)模式)。 |
'w' |
寫入模式,如果文件存在,則截?cái)辔募懭耄ǜ采w原先內(nèi)容)。如果文件不存在,則創(chuàng)建新文件并寫入 |
'a' |
追加模式,用于在文件末尾添加內(nèi)容。如果文件不存在,則創(chuàng)建新文件。 |
'x' |
獨(dú)占創(chuàng)建模式,文件不存在時(shí)創(chuàng)建新文件。如果文件已存在,則拋出錯(cuò)誤 |
'b' |
二進(jìn)制模式,與上述模式結(jié)合使用,以指示以二進(jìn)制格式打開文件(例如:‘rb’、‘wb’、‘a(chǎn)b’)。 |
't' |
文本模式(默認(rèn)模式)。。與上述模式結(jié)合使用,以指示以文本模式打開文件(例如:‘rt’、‘wt’、‘a(chǎn)t’) |
'+' |
讀寫模式,用于同時(shí)讀取和寫入文件。 |
# 寫入二進(jìn)制文件
with open("new_image.jpg", "wb") as new_binary_file:
new_binary_file.write(image_data)
??'+'
是讀寫模式,可以在同一文件上執(zhí)行讀取和寫入操作,而不必先關(guān)閉文件再重新打開,適用于需要讀取和更新文件內(nèi)容的情況。例如:
example ='Line 1: This is the first line.\n''Line 2: This is the second line.'
# 以讀寫模式打開空白文件
with open("example.txt", "w+") as file:
content = file.read()
print("原始內(nèi)容:", content)
file.write(example) # 在文件中寫入新數(shù)據(jù)
file.seek(0) # 回到文件開頭
updated_content=file.read() # 讀取更新后的內(nèi)容
print(updated_content)
??請(qǐng)注意,使用
'+'
模式時(shí),要小心處理文件指針的位置以確保讀取和寫入操作發(fā)生在您希望的位置。
-
encoding
(可選):用于文本文件的字符編碼。默認(rèn)情況下,Python將使用系統(tǒng)默認(rèn)編碼。常見的編碼包括'utf-8'
、'ascii'
等。 -
errors
(可選):處理編碼錯(cuò)誤的方式,默認(rèn)是None
,即使用默認(rèn)錯(cuò)誤處理方式。
error選項(xiàng) | 說明 |
---|---|
'strict' |
默認(rèn)選項(xiàng),表示嚴(yán)格處理編碼錯(cuò)誤,遇到無法解碼的字節(jié)序列將引發(fā)UnicodeDecodeError 異常。 |
'ignore' |
忽略無法解碼的字節(jié)序列,不會(huì)引發(fā)異常(無法解碼的部分將被丟棄)。 |
'replace' |
使用 Unicode 替代字符 U+FFFD (?)來替換無法解碼的字節(jié)。 |
'xmlcharrefreplace' |
使用 XML 字符引用來替換無法解碼的字節(jié),對(duì)于生成包含無效字符的 XML 數(shù)據(jù)很有用 |
'backslashreplace' |
使用反斜杠和十六進(jìn)制編碼的字節(jié)值來替換無法解碼的字節(jié)。 |
'namereplace' |
使用 Unicode 轉(zhuǎn)義序列來替換無法解碼的字節(jié),這樣可以保留無效字符的名稱信息。 |
-
opener
(可選):自定義打開文件的函數(shù),例如:
# 使用自定義的打開函數(shù)my_opener打開文件
def my_opener(file, flags):
return os.open(file, flags)
file = open("example.txt", "r", opener=my_opener)
8.2.2 文件指針和文件截?cái)啵╯eek&truncate)
??文件定位和截?cái)嗍翘幚砣罩疚募⑴渲梦募?、?shù)據(jù)庫文件等常見用例中的重要工具。它們?cè)试S您以靈活的方式管理文件的內(nèi)容。
- seek函數(shù)
??在 Python 中,文件指針是與文件關(guān)聯(lián)的位置標(biāo)識(shí)符,它指示了在文件中讀取或?qū)懭霐?shù)據(jù)時(shí)的當(dāng)前位置。文件指針是一個(gè)整數(shù),表示文件中的字節(jié)偏移量,其語法為:
file.seek(offset, whence)
-
offset
:一個(gè)整數(shù),表示要移動(dòng)的字節(jié)偏移量,默認(rèn)為0。 -
whence
:一個(gè)整數(shù),表示相對(duì)位置,選項(xiàng)為:-
0
表示相對(duì)于文件的開頭(默認(rèn)值)。 -
1
表示相對(duì)于文件指針的當(dāng)前位置。 -
2
表示相對(duì)于文件的末尾。
-
文件打開時(shí)文件指針默認(rèn)處于文件開頭,你也可以自由設(shè)置:
# 將文件指針移動(dòng)到文件開頭的第 100 字節(jié)處
file.seek(100, 0)
# 將文件指針從當(dāng)前位置向后移動(dòng) 50 字節(jié)
file.seek(50, 1)
# 將文件指針移動(dòng)到文件末尾前的倒數(shù)第 200 字節(jié)處
file.seek(-200, 2)
- truncate函數(shù)
??文件截?cái)嗍侵竸h除文件中的部分內(nèi)容,使文件變得更短或清空文件,你可以使用truncate
來執(zhí)行此操作,其語法為:
file.truncate(size)
??其中,size表示截?cái)鄷r(shí)指定的大?。ㄗ止?jié)單位)。如果省略size參數(shù),則文件將被截?cái)酁楫?dāng)前文件指針位置之前的大小,例如:
with open("file.txt", "r+") as file:
file.truncate(50) # 截?cái)辔募榍?0個(gè)字節(jié)
- 示例:在文件中插入數(shù)據(jù)
with open("file.txt", "r+") as file:
# 移動(dòng)文件指針到位置 30(假設(shè)文件足夠長)
file.seek(30)
# 讀取文件中剩余的內(nèi)容
remaining_data = file.read()
# 回到位置 30 并插入新文本
file.seek(30)
file.write("插入的新文本 ")
# 寫入原始內(nèi)容
file.write(remaining_data)
這將在文件的指定位置插入新文本,并保留原始內(nèi)容。
- 注意事項(xiàng)
-
使用
seek()
和truncate()
時(shí),請(qǐng)小心不要超出文件的范圍,以免發(fā)生錯(cuò)誤。 -
在使用
truncate()
時(shí),文件必須以可寫入(“w"或"r+”)模式打開。否則,將引發(fā)UnsupportedOperation
異常。 -
文件截?cái)嗍遣豢赡娴牟僮?,刪除的數(shù)據(jù)將無法恢復(fù)。謹(jǐn)慎使用。
8.2.3 讀寫函數(shù)(read、write)
以下是Python中的文件讀寫函數(shù):
方法 | 描述 | 參數(shù) |
---|---|---|
read(size) |
讀取整個(gè)文件的內(nèi)容為,返回一個(gè)字符串。 | size可選,指定要讀取的最大字節(jié)數(shù)。未指定時(shí)默認(rèn)讀取整個(gè)文件。 |
readline(size) |
逐行讀取文件的內(nèi)容,即每次讀取一行。 | size可選,指定一行中要讀取的最大字節(jié)數(shù)。未指定時(shí)默認(rèn)讀取整行內(nèi)容。 |
readlines(hint) |
默認(rèn)讀取整個(gè)文件的內(nèi)容,并將每行存儲(chǔ)為列表中的一個(gè)元素。 | hint可選,含義同上 |
for 循環(huán)逐行讀取 |
使用 for 循環(huán)逐行讀取文件的內(nèi)容。 |
|
write(str) |
根據(jù)選擇的模式,將指定的字符串寫入文件的當(dāng)前位置。 |
write 函數(shù)沒有額外參數(shù) |
close |
關(guān)閉文件,釋放文件資源并確保數(shù)據(jù)被保存。 |
read和readlines的區(qū)別:
- read(size):讀取前size個(gè)字節(jié)的數(shù)據(jù),不關(guān)心行的分隔符,最后返回一個(gè)字符串。另外文件指針將保持在讀取數(shù)據(jù)之后的位置。
- readlines(size):讀取前size個(gè)字節(jié)的數(shù)據(jù),包含分隔符(通常是換行符
\n
),返回字符串列表(每一行)。最后,文件指針將移到下一個(gè)未讀行的開頭。
示例:
"""
example.txt
Line 1: This is the first line.
Line 2: This is the second line.
"""
file = open('example.txt', 'r')
data1 = file.read(20) # 讀取前 20 個(gè)字節(jié),結(jié)果:"Line 1: This is the "
data2 = file.readlines(30) # 讀取前 30 個(gè)字節(jié),結(jié)果:["first line.\n", "Line 2: This is the second line."]
file.close()
8.2.4 上下文管理器(with)
官方文檔: with 上下文管理器
??使用上下文管理器非常簡單,只需在 with
語句中創(chuàng)建并使用它即可。下面是一個(gè)使用上下文管理器的示例,以打開和關(guān)閉文件為例:
# 使用上下文管理器自動(dòng)關(guān)閉文件
with open("example.txt", "r") as file:
content = file.read()
print(content)
# 在此處文件已自動(dòng)關(guān)閉,無需手動(dòng)關(guān)閉
??在這個(gè)示例中,open()
函數(shù)返回一個(gè)文件對(duì)象,它是一個(gè)上下文管理器。當(dāng)進(jìn)入 with
代碼塊時(shí),__enter__()
方法被調(diào)用,文件被打開。當(dāng)代碼塊執(zhí)行完畢后,無論正常執(zhí)行還是出現(xiàn)異常,__exit__()
方法都會(huì)被調(diào)用,確保文件被正確關(guān)閉。
??你還可以創(chuàng)建自定義的上下文管理器,以管理其他資源(如數(shù)據(jù)庫連接、網(wǎng)絡(luò)連接等)。要?jiǎng)?chuàng)建自定義上下文管理器,只需定義一個(gè)類,并實(shí)現(xiàn) __enter__()
和 __exit__()
方法。以下是一個(gè)示例:
# 創(chuàng)建MyContextManager類實(shí)現(xiàn)一個(gè)簡單的上下文管理器
class MyContextManager:
def __enter__(self):
print("Entering the context")
# 在此處可以初始化資源
return self # 返回一個(gè)對(duì)象(可選)
def __exit__(self, exc_type, exc_value, traceback):
print("Exiting the context")
# 在此處進(jìn)行清理操作,如關(guān)閉資源
# 使用自定義上下文管理器
with MyContextManager() as cm:
print("Inside the context")
# 在此處自定義上下文管理器的__exit__()方法被調(diào)用,進(jìn)行資源清理
??上下文管理器是一個(gè)非常強(qiáng)大和有用的Python功能,它確保了資源的正確分配和釋放,使代碼更加健壯和可維護(hù)。無論是使用內(nèi)置的上下文管理器還是創(chuàng)建自定義的上下文管理器,都可以提高代碼的可讀性和可維護(hù)性。
8.3 讀寫excel/csv文件
參考pandas官方文檔《Input/output》、openpyxl官方文檔、xlrd官方文檔
??前面講的都是讀寫文本文件和二進(jìn)制文件,如果要處理excel或者csv文件,可以使用pandasku、openpyxl庫或者xird,下面進(jìn)行簡單介紹。
8.3.1 pandas讀寫excel/csv文件
pandas 可以讀取的文件格式有很多,下面一一介紹。
1. 讀取 csv, excel, txt 文件
pandas.read_csv(filepath, *, sep=_NoDefault.no_default, delimiter=None, header='infer', names=_NoDefault.no_default, index_col=None, usecols=None, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skipinitialspace=False, skiprows=None, skipfooter=0, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, skip_blank_lines=True, parse_dates=None, infer_datetime_format=_NoDefault.no_default, keep_date_col=False, date_parser=_NoDefault.no_default, date_format=None, dayfirst=False, cache_dates=True, iterator=False, chunksize=None, compression='infer', thousands=None, decimal='.', lineterminator=None, quotechar='"', quoting=0, doublequote=True, escapechar=None, comment=None, encoding=None, encoding_errors='strict', dialect=None, on_bad_lines='error', delim_whitespace=False, low_memory=True, memory_map=False, float_precision=None, storage_options=None, dtype_backend=_NoDefault.no_default)[source]
df_csv = pd.read_csv('data/my_csv.csv')
df_txt = pd.read_table('data/my_table.txt')
df_excel = pd.read_excel('data/my_excel.xlsx')
這里有一些常用的公共參數(shù):
-
filepath
:可以是文件路徑或者URL,例如本地文件file://localhost/path/to/table.csv。 -
sep
:分割符。pd.read_csv
默認(rèn)使用逗號(hào)作為分隔符,pd.read_table
默認(rèn)使用制表符\t
作為分隔符。 -
header='infer'
: 指定用作列名的行號(hào),默認(rèn)為0,表示第一行??梢栽O(shè)置header=None
不使用列名。 -
names
:自定義列名,以列表形式提供。如果設(shè)置了header=None
,則可以使用該參數(shù) -
index_col
:表示把某一列或幾列作為列索引,可以是整數(shù)、字符串或列表 -
usecols
:表示要讀取的列,可以是列號(hào)、列名或者列名的列表,默認(rèn)讀取所有的列 -
parse_dates
:指定要解析為日期時(shí)間的列,可以是列號(hào)或列名的列表 -
date_parser
:使用自定義函數(shù)解析日期時(shí)間列 -
nrows
:表示讀取的數(shù)據(jù)行數(shù)。 -
skiprows
:要跳過的行數(shù)(從文件頂部開始計(jì)算) -
skipfooter
:要從文件底部跳過的行數(shù)(不支持所有的解析器) -
na_values
:用于將特定值識(shí)別為缺失值的列表或字典
下面是具體的示例:
# 1.讀取txt文件,不設(shè)置列名
pd.read_table('data/my_table.txt', header=None)
Out[10]:
0 1 2 3 4
0 col1 col2 col3 col4 col5
1 2 a 1.4 apple 2020/1/1
2 3 b 3.4 banana 2020/1/2
3 6 c 2.5 orange 2020/1/5
4 5 d 3.2 lemon 2020/1/7
# 2.設(shè)置索引列,并跳過前兩行
pd.read_csv('data/my_csv.csv', index_col=['col1', 'col2'],skiprows=[0, 1])
Out[11]:
col3 col4 col5
col1 col2
6 c 2.5 orange 2020/1/5
5 d 3.2 lemon 2020/1/7
# 3.只讀取前兩列,并設(shè)置列名
pd.read_table('data/my_table.txt', usecols=['col1', 'col2'],header=None,names=[列1','列2'])
Out[12]:
列1 列2
0 2 a
1 3 b
2 6 c
3 5 d
# 4.使用自定義函數(shù)解析指定'col5'的日期解析格式,只讀前兩行
date_parser = lambda x: pd.to_datetime(x, format='%Y-%m-%d')
pd.read_csv('data/my_csv.csv', parse_dates=['col5'], date_parser=date_parser,nrows=2)
Out[13]:
col1 col2 col3 col4 col5
0 2 a 1.4 apple 2020-01-01
1 3 b 3.4 banana 2020-01-02
# 5. 將文件中的'N/A', 'NA'字符視為缺失值,并替換為NaN
pd.read_csv('data/my_table.txt',header=None,na_values=['N/A', 'NA'])
另外read_excel
還有一些常用參數(shù):
-
sheet_name
:指定要讀取的工作表名稱,默認(rèn)為0,表示第一個(gè)工作表??梢允褂米址üぷ鞅砻Q)或整數(shù)(工作表索引)。 -
engine
:指定要使用的解析引擎,例如’xlrd’或’openpyxl’。默認(rèn)根據(jù)文件擴(kuò)展名自動(dòng)選擇
??在讀取 txt 文件時(shí),經(jīng)常遇到分隔符非空格的情況, read_table 有一個(gè)分割參數(shù) sep ,它使得用戶可以自定義分割符號(hào),進(jìn)行 txt 數(shù)據(jù)的讀取。例如,下面的讀取的表以 |||| 為分割:
pd.read_table('data/my_table_special_sep.txt')
Out[15]:
col1 |||| col2
0 TS |||| This is an apple.
1 GQ |||| My name is Bob.
2 WT |||| Well done!
上面的結(jié)果顯然不是理想的,這時(shí)可以使用 sep ,同時(shí)需要指定引擎為 python
pd.read_table('data/my_table_special_sep.txt',
sep=' \|\|\|\| ', engine='python')
Out[16]:
col1 col2
0 TS This is an apple.
1 GQ My name is Bob.
2 WT Well done!
3 PT May I help you?
??在使用
read_table
的時(shí)候需要注意,參數(shù)sep
中使用的是正則表達(dá)式,因此需要對(duì)|
進(jìn)行轉(zhuǎn)義變成\|
,否則無法讀取到正確的結(jié)果。
2. 寫入csv, excel, txt 文件
??pandas 中沒有定義 to_table 函數(shù),但是 to_csv 可以保存為 txt 文件(也可以保存csv文件),并且允許自定義分隔符,常用制表符 \t
分割:
# 當(dāng)索引沒有特殊意義的時(shí)候,可以使用index=False 去除索引
df.to_csv('data/my_txt_saved.txt', sep='\t', index=False)
??如果想要把表格快速轉(zhuǎn)換為 markdown 和 latex 語言,可以使用 to_markdown
和 to_latex
函數(shù)(需要先安裝 tabulate 包)。
print(df_csv.to_markdown())
col1 | col2 | col3 | col4 | col5 | |
---|---|---|---|---|---|
0 | 2 | a | 1.4 | apple | 2020/1/1 |
1 | 3 | b | 3.4 | banana | 2020/1/2 |
2 | 6 | c | 2.5 | orange | 2020/1/5 |
3 | 5 | d | 3.2 | lemon | 2020/1/7 |
print(df_csv.to_latex())
\begin{tabular}{lrlrll}
\toprule
{} & col1 & col2 & col3 & col4 & col5 \\
\midrule
0 & 2 & a & 1.4 & apple & 2020/1/1 \\
1 & 3 & b & 3.4 & banana & 2020/1/2 \\
2 & 6 & c & 2.5 & orange & 2020/1/5 \\
3 & 5 & d & 3.2 & lemon & 2020/1/7 \\
\bottomrule
\end{tabular}
8.3.2 openpyxl庫
??openpyxl 是一個(gè)非常強(qiáng)大和廣泛使用的庫。它允許你讀取、寫入和操作Excel文件(.xlsx 格式)。使用之前,需要進(jìn)行安裝:pip install openpyxl
。下面列舉openpyxl的主要操作:
操作/函數(shù) | 描述 |
---|---|
openpyxl.load_workbook(filename) |
打開一個(gè)Excel工作簿并返回工作簿對(duì)象。 |
workbook.create_sheet(title) |
創(chuàng)建一個(gè)新的工作表并返回工作表對(duì)象。 |
workbook.active |
獲取或設(shè)置當(dāng)前活動(dòng)的工作表。 |
workbook.sheetnames |
返回工作簿中所有工作表的名稱列表。 |
worksheet.cell(row, column) |
獲取或設(shè)置指定行列的單元格。 |
worksheet.iter_rows() |
遍歷工作表中的行,返回單元格值的生成器。 |
worksheet.iter_cols() |
遍歷工作表中的列,返回單元格值的生成器。 |
worksheet.title |
獲取或設(shè)置工作表的名稱。 |
worksheet.max_row |
獲取工作表中的最大行數(shù)。 |
worksheet.max_column |
獲取工作表中的最大列數(shù)。 |
worksheet['A1'] |
使用字母和數(shù)字索引獲取單元格的值。 |
worksheet.append([data]) |
向工作表追加一行數(shù)據(jù)。 |
worksheet.delete_rows(index, count) |
刪除工作表中指定索引位置的行。 |
worksheet.insert_rows(index, count) |
在指定位置插入指定數(shù)量的空白行。 |
worksheet.delete_cols(index, count) |
刪除工作表中指定索引位置的列。 |
worksheet.insert_cols(index, count) |
在指定位置插入指定數(shù)量的空白列。 |
workbook.save(filename) |
保存工作簿到指定文件。 |
workbook.remove(sheet) |
從工作簿中移除指定工作表。 |
workbook.copy_worksheet(sheet) |
復(fù)制工作表到同一工作簿或另一個(gè)工作簿。 |
import openpyxl
# 打開一個(gè)現(xiàn)有的工作簿
workbook = openpyxl.load_workbook('example.xlsx')
# 選擇工作簿中的工作表(通過名稱)
worksheet = workbook['Sheet1']
# 讀取單元格數(shù)據(jù)
value = worksheet.cell(row=1, column=1).value
# 寫入單元格數(shù)據(jù)
worksheet.cell(row=2, column=2, value='Hello, World!')
# 保存工作簿
workbook.save('new_example.xlsx')
# 創(chuàng)建新的工作表
new_sheet = workbook.create_sheet('NewSheet')
# 遍歷工作表數(shù)據(jù)
print('工作表數(shù)據(jù):')
for row in worksheet.iter_rows(values_only=True):
print(row)
8.3.3 xlrd庫(打開加密excel)
xlrd 也是一個(gè)用于讀取 Excel 文件的 Python 庫,主要函數(shù)如下:
操作/函數(shù) | 描述 |
---|---|
xlrd.open_workbook(filename) |
打開一個(gè) Excel 工作簿并返回工作簿對(duì)象。 |
workbook.sheet_names() |
獲取工作簿中所有工作表的名稱。 |
workbook.sheet_by_name(name) |
根據(jù)工作表名稱選擇工作表。 |
workbook.sheet_by_index(index) |
根據(jù)索引選擇工作表。 |
worksheet.cell_value(row, col) |
讀取指定行列的單元格內(nèi)容。 |
worksheet.nrows |
獲取工作表的行數(shù)。 |
worksheet.ncols |
獲取工作表的列數(shù)。 |
worksheet.row(row_num) |
返回指定行的所有單元格內(nèi)容(以列表形式)。 |
worksheet.col(col_num) |
返回指定列的所有單元格內(nèi)容(以列表形式)。 |
xlrd.xldate_as_datetime(date, datemode) |
將 Excel 日期值轉(zhuǎn)換為 Python 的 datetime 對(duì)象。 |
workbook.close() |
關(guān)閉工作簿。 |
# 導(dǎo)入所需的庫和模塊
import pandas as pd
import numpy as np
import os
from xlrd import *
import win32com.client
import sys
# 設(shè)置要打開的Excel文件的文件路徑
filename = '縮孔數(shù)據(jù)庫/2023縮孔統(tǒng)計(jì)更新至9-4.xlsm'
color = ['QAC', 'G41', 'QAB', 'KAD'] # 設(shè)置要查找的顏色
xlApp = win32com.client.Dispatch("Excel.Application") # 創(chuàng)建一個(gè)Excel應(yīng)用程序?qū)ο?/span>
password = 'xxxxxxxx' # Excel文件的密碼(如果有密碼保護(hù)的話)
# 使用只讀模式打開工作簿
# Format=None表示讓 Excel 自動(dòng)識(shí)別文件格式。你也可以明確指定,例如 Format=1 表示打開的是 xls 格式文件。
xlwb = xlApp.Workbooks.Open(Filename=os.path.abspath(filename),
ReadOnly=True,
Format=None,
Password=password)
xlws = xlwb.Sheets(3) # 選擇工作簿中的第3張工作表(索引從1開始)
cols = 15 # 選擇要讀取的列數(shù)
rows = xlws.UsedRange.Rows.Count # 獲取工作表的行數(shù)
# 從工作表中讀取(1, 1)到(rows, cols)之間的單元格,其實(shí)就是前15列
content = list(xlws.Range(xlws.Cells(1, 1), xlws.Cells(rows, cols)).Value)
# 將讀取的數(shù)據(jù)轉(zhuǎn)換為Pandas DataFrame
df = pd.DataFrame(content)
8.4 os模塊
8.4.1 os模塊常用函數(shù)
官方文檔:《os — 多種操作系統(tǒng)接口》、《os.path — 常用路徑操作》
??如果你只是想讀寫一個(gè)文件,請(qǐng)參閱 open(),如果你想操作文件路徑,請(qǐng)參閱 os.path 模塊,如果你想讀取通過命令行給出的所有文件中的所有行,請(qǐng)參閱 fileinput 模塊。 為了創(chuàng)建臨時(shí)文件和目錄,請(qǐng)參閱 tempfile 模塊,對(duì)于高級(jí)文件和目錄處理,請(qǐng)參閱 shutil 模塊。
??os
模塊是 Python 的標(biāo)準(zhǔn)庫之一,提供了與操作系統(tǒng)交互的功能。它允許您執(zhí)行與文件系統(tǒng)、目錄、文件路徑等相關(guān)的操作。以下是 os
模塊的一些主要功能:
文件和目錄操作函數(shù) | 描述 |
---|---|
os.mkdir(path) |
創(chuàng)建一個(gè)新的目錄。 |
os.rmdir(path) |
刪除一個(gè)空目錄。 |
os.remove(path) |
刪除文件。 |
os.rename(src, dst) |
重命名文件或目錄。 |
os.getcwd() |
返回當(dāng)前工作目錄。 |
os.listdir(path) |
返回目錄中的文件和子目錄的列表。 |
os.walk(top, topdown=True, onerror=None, followlinks=False) |
生成目錄樹中的文件名。 |
os.chmod(path, mode) |
更改文件或目錄的權(quán)限。 |
os.stat(path) |
獲取文件或目錄的狀態(tài)信息。 |
路徑操作函數(shù) | 描述 |
---|---|
os.path.join(path1, path2, ...) |
連接路徑的各個(gè)部分,以創(chuàng)建完整路徑。 |
os.path.abspath(path) |
返回絕對(duì)路徑。 |
os.path.exists(path) |
檢查文件或目錄是否存在。 |
os.path.isdir(path) |
檢查路徑是否為目錄。 |
os.path.isfile(path) |
檢查路徑是否為文件。 |
os.path.basename(path) |
返回路徑中的文件名。 |
os.path.dirname(path) |
返回路徑中的目錄名。 |
os.path.split(path) |
分割路徑,返回目錄名和文件名的元組。 |
環(huán)境變量函數(shù) | 描述 |
---|---|
os.environ |
包含系統(tǒng)環(huán)境變量的字典。 |
os.getenv(key, default) |
獲取指定環(huán)境變量的值。 |
系統(tǒng)命令函數(shù) | 描述 |
---|---|
os.name |
返回操作系統(tǒng)的名稱(例如,‘posix’ 或 ‘nt’)。 |
os.uname() |
返回有關(guān)當(dāng)前系統(tǒng)的詳細(xì)信息(僅在 POSIX 系統(tǒng)上可用)。 |
os.system(command) |
在子shell中執(zhí)行系統(tǒng)命令。 |
os.spawn*() |
生成新進(jìn)程。 |
os.kill(pid, signal) |
終止進(jìn)程 |
8.4.2 os.walk函數(shù)
??os.walk()
是一個(gè)非常實(shí)用的函數(shù),用于在目錄樹中遍歷文件和子目錄。它返回一個(gè)生成器,該生成器產(chǎn)生三元組 (dirpath, dirnames, filenames)
,其中:
-
dirpath
:當(dāng)前目錄的路徑。 -
dirnames
:當(dāng)前目錄下的子目錄列表,如果沒有子目錄,則返回空列表 -
filenames
:當(dāng)前目錄下的文件列表。
下面是一個(gè)詳細(xì)說明 os.walk()
用法的示例,假設(shè)我們有以下目錄結(jié)構(gòu):
my_folder
│
├── dir1
│ ├── file1.txt
│ └── file2.txt
│
├── dir2
│ ├── sub_dir
│ │ ├── file3.txt
│ │ └── file4.txt
│ └── file5.txt
│
└── file6.txt
我們可以使用 os.walk()
遍歷這個(gè)目錄樹并打印出每個(gè)目錄中的子目錄和文件:
import os
# 設(shè)置要遍歷的根目錄
root_directory = 'my_folder'
# 使用 os.walk() 遍歷目錄樹
for dirpath, dirnames, filenames in os.walk(root_directory):
# 打印當(dāng)前目錄路徑
print(f"Current Directory: {dirpath}")
# 打印當(dāng)前目錄下的子目錄
print("Subdirectories:")
for dirname in dirnames:
print(f" - {dirname}")
# 打印當(dāng)前目錄下的文件
print("Files:")
for filename in filenames:
print(f" - {filename}")
# 打印一個(gè)分隔線
print("-" * 40)
運(yùn)行這個(gè)代碼會(huì)產(chǎn)生如下輸出:
Current Directory: my_folder
Subdirectories:
- dir1
- dir2
Files:
- file6.txt
----------------------------------------
Current Directory: my_folder\dir1
Subdirectories:
Files:
- file1.txt
- file2.txt
----------------------------------------
Current Directory: my_folder\dir2
Subdirectories:
- sub_dir
Files:
- file5.txt
----------------------------------------
Current Directory: my_folder\dir2\sub_dir
Subdirectories:
Files:
- file3.txt
- file4.txt
----------------------------------------
8.5 shutil 模塊(移動(dòng)、復(fù)制、壓縮文件)
參考《shutil — 高階文件操作》
??shutil
模塊是Python標(biāo)準(zhǔn)庫中的一個(gè)強(qiáng)大工具,用于文件和目錄操作。它提供了許多函數(shù),可用于復(fù)制、移動(dòng)、刪除文件和目錄,以及執(zhí)行各種文件操作任務(wù),以下是其主要用法:
方法 | 描述 | 示例 |
---|---|---|
shutil.copy(src, dst) |
復(fù)制文件從源路徑到目標(biāo)路徑。 | shutil.copy('source.txt', 'destination.txt') |
shutil.move(src, dst) |
移動(dòng)文件或重命名文件。 | shutil.move('old_name.txt', 'new_name.txt') |
shutil.copytree(src, dst) |
遞歸復(fù)制整個(gè)文件夾及其內(nèi)容。 | shutil.copytree('source_folder', 'destination_folder') |
shutil.rmtree(path) |
遞歸刪除整個(gè)目錄樹,包括所有文件和子目錄。 | shutil.rmtree('folder_to_delete') |
shutil.make_archive(base_name, format) |
創(chuàng)建歸檔文件,例如 ZIP 文件。 | hutil.make_archive(archive_name, format='zip', root_dir='folder_to_compress') |
shutil.unpack_archive(filename, extract_dir) |
解壓縮歸檔文件。 | shutil.unpack_archive('my_archive.zip', 'extracted_folder') |
歸檔函數(shù)語法為:
shutil.make_archive(base_name, format, root_dir=None, base_dir=None)
參數(shù)含義:
-
base_name
:歸檔文件的基本名稱,不包括文件擴(kuò)展名。例如,如果設(shè)置為'my_archive'
,則將創(chuàng)建'my_archive.zip'
或'my_archive.tar.gz'
等文件。 -
format
:歸檔文件的格式,通常是字符串,可以是'zip'
、'tar'
、'gztar'
、'bztar'
、'xztar'
等。
‘gztar’:gzip 壓縮的 tar 歸檔文件。
‘bztar’:bzip2 壓縮的 tar 歸檔文件。
‘xztar’:xz 壓縮的 tar 歸檔文件 -
root_dir
(可選):要?dú)w檔的根目錄,如果不提供,默認(rèn)為當(dāng)前工作目錄。 -
base_dir
(可選):要?dú)w檔的基本目錄,如果提供,將在root_dir
下創(chuàng)建一個(gè)子目錄,并將其內(nèi)容歸檔。
tar是未壓縮的tar 歸檔文件,后三者分別是gzip格式、bzip2格式和xz格式壓縮的tar文件。
下面是一個(gè)示例假設(shè)有以下目錄結(jié)構(gòu):
my_project/
├── source/
│ ├── file1.txt
│ ├── file2.txt
│ └── subfolder/
│ └── file3.txt
└── other_folder/
└── file4.txt
現(xiàn)在用zip格式只歸檔source和other_folder目錄到指定目錄下,代碼可以寫為:
import shutil
# 源目錄的根目錄
source_root_dir = 'my_project/'
# 要?dú)w檔的子目錄列表
subdirectories_to_archive = ['source/', 'other_folder/']
# 目標(biāo)位置
destination_dir = 'destination_directory/'
# 歸檔文件的名稱和格式
archive_name = 'my_archive'
format = 'zip'
# 創(chuàng)建 ZIP 歸檔文件,指定 root_dir 為源目錄,base_dir 為子目錄列表
shutil.make_archive(
archive_name, format, root_dir=source_root_dir, base_dir=subdirectories_to_archive
)
# 將歸檔文件移動(dòng)到目標(biāo)位置
shutil.move(f'{archive_name}.{format}', destination_dir)
# 解壓到source目錄下
shutil.unpack_archive(archive_file, 'my_project/source/')
8.6 Python數(shù)據(jù)的序列化
Pyhon官方文檔:json模塊、pickle模塊
8.6.1 數(shù)據(jù)的序列化和反序列化
??前者介紹的read、write這些方法,都是進(jìn)行字符串的讀取,即使是數(shù)字,也是轉(zhuǎn)成字符串格式,而如果碰到嵌套列表和字典等更復(fù)雜的數(shù)據(jù)類型時(shí),手動(dòng)解析將會(huì)變得非常復(fù)雜。這就涉及到數(shù)據(jù)的序列化和反序列化:
-
序列化(Serialization):
??將數(shù)據(jù)從其原始數(shù)據(jù)結(jié)構(gòu)(通常是Python對(duì)象)轉(zhuǎn)換為一種可以在不同程序、不同計(jì)算機(jī)或不同時(shí)間之間傳輸或存儲(chǔ)的格式的過程,通常轉(zhuǎn)換為文本或二進(jìn)制表示,以便能夠保存到文件、發(fā)送到網(wǎng)絡(luò)、存儲(chǔ)在數(shù)據(jù)庫中或在其他情況下傳輸和使用。
??在Python中,常見的序列化方法包括使用JSON(JavaScript Object Notation)或Pickle(Python特定的序列化格式)等。 -
反序列化(Deserialization):將序列化后的數(shù)據(jù)重新還原為可以在程序中操作的Python對(duì)象,用于在程序中進(jìn)一步處理數(shù)據(jù)。。
??python提供了json
標(biāo)準(zhǔn)庫,可以使用 JSON (JavaScript Object Notation)格式進(jìn)行數(shù)據(jù)的交換。JSON數(shù)據(jù)是純文本,易于閱讀和編寫,也易于解析和生成,非常適合處理復(fù)雜結(jié)構(gòu)的數(shù)據(jù),在Web開發(fā)、API通信以及配置文件中廣泛使用。
8.6.2 json模塊
??Python的json
模塊允許你序列化Python對(duì)象(將其轉(zhuǎn)換為JSON格式)和反序列化JSON數(shù)據(jù)(將JSON數(shù)據(jù)轉(zhuǎn)換為Python對(duì)象),其主要方法有:
json方法 | 描述 |
---|---|
json.dumps(obj) |
將Python對(duì)象序列化為JSON字符串 |
json.loads(json_str) |
將JSON字符串反序列化為Python對(duì)象 |
json.dump(obj, file) |
將Python對(duì)象序列化為JSON并保存到文件中 |
json.load(file) |
從文件中加載JSON數(shù)據(jù)并反序列化為Python對(duì)象 |
下面是示例代碼:
# 將Python對(duì)象轉(zhuǎn)換為JSON
import json
data = {
"name": "John",
"age": 30,
"city": "New York"
}
# 將Python字典轉(zhuǎn)換為JSON字符串
json_data = json.dumps(data)
# 保存JSON字符串到文件
with open("data.json", "w") as json_file:
json.dump(data, json_file)
import json
# 從JSON字符串反序列化為Python字典
json_data = '{"name": "John", "age": 30, "city": "New York"}'
data = json.loads(json_data)
# 從文件中加載JSON數(shù)據(jù)
with open("data.json", "r") as json_file:
data = json.load(json_file)
8.6.3 pickle模塊
??pickle
是Python的一種序列化模塊,它能夠?qū)ython對(duì)象轉(zhuǎn)換為二進(jìn)制格式,所以它可以序列化幾乎所有Python對(duì)象,包括自定義類的實(shí)例和函數(shù)、模型等。以下是其常用的方法:
pickle模塊方法 | 描述 |
---|---|
pickle.dumps(obj[, protocol]) |
將Python對(duì)象序列化為包含二進(jìn)制數(shù)據(jù)的字符串 |
pickle.loads(bytes_object) |
從包含二進(jìn)制數(shù)據(jù)的字符串中反序列化為Python對(duì)象 |
pickle.dump(obj, file[, protocol]) |
將Python對(duì)象序列化為二進(jìn)制數(shù)據(jù)并保存到文件中 |
pickle.load(file) |
從文件中加載二進(jìn)制數(shù)據(jù)并反序列化為Python對(duì)象 |
pickle.Pickler(file[, protocol]) |
創(chuàng)建一個(gè)Pickler對(duì)象,用于將對(duì)象序列化到文件或文件類中 |
pickle.Unpickler(file) |
創(chuàng)建一個(gè)Unpickler對(duì)象,用于從文件或文件類中反序列化對(duì)象 |
pickle.HIGHEST_PROTOCOL |
常量,表示pickle使用的最高協(xié)議版本(通常是最新的) |
??上述列表中,可選參數(shù)protocol
用于指定序列化使用的協(xié)議版本,默認(rèn)為最高版本。列表列舉出三種序列化和反序列化方法,區(qū)別如下:
- pickle.dump:用于將Python對(duì)象序列化為二進(jìn)制數(shù)據(jù)并保存到文件中。
- pickle.dumps:用于將Python對(duì)象序列化為包含二進(jìn)制數(shù)據(jù)的字符串(不保存到文件)。
- pickle.Pickler:創(chuàng)建一個(gè)Pickler對(duì)象,可用于處理多個(gè)Python對(duì)象。
下面舉例說明:
import pickle
# 示例數(shù)據(jù)
data1 = {
"name": "Alice",
"age": 25,
"city": "London"
}
data2 = {
"name": "Bob",
"age": 30,
"city": "New York"
}
# 使用 pickle.dump 進(jìn)行序列化,結(jié)果保存在文件中
with open("data.pkl", "wb") as pickle_file:
pickle.dump(data1, pickle_file)
# 使用 pickle.load 讀取文件,進(jìn)行對(duì)應(yīng)的反序列化
with open("data.pkl", "rb") as pickle_file:
loaded_data1 = pickle.load(pickle_file)
'---------------------------------------------------------------'
# 使用 pickle.dumps 進(jìn)行序列化,結(jié)果賦值給一個(gè)變量
pickle_data = pickle.dumps(data2)
# 使用 pickle.loads 反序列化這個(gè)變量
loaded_data2 = pickle.loads(pickle_data)
'---------------------------------------------------------------'
# 使用 pickle.Pickler 和 pickle.Unpickler 進(jìn)行序列化和反序列化
with open("data.pkl", "wb") as pickle_file:
pickler = pickle.Pickler(pickle_file)
pickler.dump(data1) # 序列化數(shù)據(jù)1
pickler.dump(data2) # 序列化數(shù)據(jù)2
with open("data.pkl", "rb") as pickle_file:
unpickler = pickle.Unpickler(pickle_file)
loaded_data1_pickled = unpickler.load() # 反序列化數(shù)據(jù)1
loaded_data2_pickled = unpickler.load() # 反序列化數(shù)據(jù)2
# 打印反序列化后的數(shù)據(jù)
print("Loaded Data 1:", loaded_data1)
print("Loaded Data 2:", loaded_data2)
print("Loaded Data 1 (Pickler):", loaded_data1_pickled)
print("Loaded Data 2 (Pickler):", loaded_data2_pickled)
??
Pickler
對(duì)象可以將多個(gè)序列化的對(duì)象存儲(chǔ)在同一個(gè)文件中,Unpickler
對(duì)象在加載時(shí)會(huì)按順序逐個(gè)讀取和反序列化這些對(duì)象,所以上述代碼中,會(huì)多次調(diào)用unpickler.load()
來逐個(gè)加載這些對(duì)象,并將它們分配給不同的變量。
總結(jié): json和pickle的區(qū)別
-
JSON(JavaScript Object Notation)
- 用于文本序列化格式,適用于序列化簡單的數(shù)據(jù)結(jié)構(gòu),如字典、列表、字符串和數(shù)字,人類更容易解讀。
- 通用性強(qiáng),可以在不同編程語言之間輕松交換數(shù)據(jù)。
- 安全性高,對(duì)一個(gè)不信任的JSON進(jìn)行反序列化的操作本身不會(huì)造成任意代碼執(zhí)行漏洞。
-
Pickle
- Python特定的二進(jìn)制序列化格式,可以用于序列化幾乎所有Python對(duì)象,包括自定義類的實(shí)例和函數(shù)。
- pickle序列化是Python專用的,不適合與其他編程語言交互
- pickle可以加載包含惡意代碼的數(shù)據(jù),所以需要謹(jǐn)慎使用(只在信任的源中使用pickle)。
8.6.4 示例:使用pickle保存lightGBM模型&加載預(yù)測(cè)
見我的另一篇帖子《lightGBM實(shí)戰(zhàn)》
在Windows 10系統(tǒng)的命令提示符(CMD)中,要切換到D:\VM17\x64目錄,你可以使用以下命令:文章來源:http://www.zghlxwxcb.cn/news/detail-704877.html
cd /d D:\VM17\x64
這個(gè)命令中:文章來源地址http://www.zghlxwxcb.cn/news/detail-704877.html
-
cd
是用來改變當(dāng)前目錄的命令。 -
/d
選項(xiàng)用于切換到指定的驅(qū)動(dòng)器(在這種情況下是D:\),即使當(dāng)前工作目錄在不同的驅(qū)動(dòng)器上。 -
D:\VM17\x64
是你要切換到的目標(biāo)目錄的路徑。
到了這里,關(guān)于Python3.11教程3:模塊和包(pip/conda)、文件系統(tǒng)(os/ shutil/json/pickle/openpyxl/xlrd)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!