day11-模組

死不悔改奇男子發表於2024-04-06

1. 自定義模組

1.1 模組和包

import hashlib


def encrypt(data):
    """ 資料加密 """
    hash_object = hashlib.md5()
    hash_object.update(data.encode('utf-8'))
    return hash_object.hexdigest()


user = input("請輸入使用者名稱:")
pwd = input("請輸入密碼:")
md5_password = encrypt(pwd)

message = "使用者名稱:{},密碼:{}".format(user, md5_password)
print(message)

在開發簡單的程式時,使用一個py檔案就可以搞定,如果程式比較龐大,需要些10w行程式碼,此時為了,程式碼結構清晰,將功能按照某種規則拆分到不同的py檔案中,使用時再去匯入即可。另外,當其他專案也需要此專案的某些模組時,也可以直接把模組拿過去使用,增加重用性。

如果按照某個規則進行拆分,發現拆分到 commons.py 中函式太多,也可以透過資料夾來進行再次拆分,例如:

├── commons
│   ├── convert.py
│   ├── page.py
│   └── utils.py
└── run.py

image

在Python中一般對檔案和檔案的稱呼(很多開發者的平時開發中也有人都稱為模組)

  • 一個py檔案,模組(module)。
  • 含多個py檔案的資料夾,包(package)。

注意:在包(資料夾)中有一個預設內容為空的__init__.py的檔案,一般用於描述當前包的資訊(在匯入他下面的模組時,也會自動載入)。

  • py2必須有,如果沒有匯入包就會失敗。
  • py3可有可無。

1.2 匯入

當定義好一個模組或包之後,如果想要使用其中定義的功能,必須要先匯入,然後再能使用。

匯入,其實就是將模組或包載入的記憶體中,以後再去記憶體中去拿就行。

關於導如時的路徑:

在Python內部預設設定了一些路徑,匯入模組或包時,都會按照指定順序逐一去特定的路徑查詢。

import sys
print(sys.path)

想要匯入任意的模組和包,都必須寫在如下路徑下,才能被找到。

也可以自動手動在sys.path中新增指定路徑,然後再匯入可以,例如:

import sys
sys.path.append("路徑A")

import xxxxx  # 匯入路徑A下的一個xxxxx.py檔案
  1. 你以後寫模組名稱時,千萬不能和內建和第三方的同名(新手容易犯錯誤)。
  2. 專案執行檔案一般都在專案根目錄,如果執行檔案巢狀的記憶體目錄,就需要自己手動在sys.path中新增路徑。
    image
  3. pycharm中預設會將專案目錄加入到sys.path中

關於匯入的方式:

匯入本質上是將某個檔案中的內容先載入到記憶體中,然後再去記憶體中拿過來使用。而在Python開發中常用的匯入的方式有2類方式,每類方式都也多種情況。

  • 第一類:import xxxx(開發中,一般多用於匯入sys.path目錄下的一個py檔案)

    • 模組級別

      ├── commons
      │   ├── __init__.py
      │   ├── convert.py
      │   ├── page.py
      │   ├── tencent
      │   │   ├── __init__.py
      │   │   ├── sms.py
      │   │   └── wechat.py
      │   └── utils.py
      ├── many.py
      └── run.py
      

      image

    • 包級別

      ├── commons
      │   ├── __init__.py
      │   ├── convert.py
      │   ├── page.py
      │   └── utils.py
      ├── third
      │   ├── __init__.py
      │   ├── ali
      │   │   └── oss.py
      │   └── tencent
      │       ├── __init__.py
      │       ├── __pycache__
      │       ├── sms.py
      │       └── wechat.py
      └── run.py
      

      image

  • 第二類:from xxx import xxx 【常用】,一般適用於多層巢狀和匯入模組中某個成員的情況。

    • 成員級別

      ├── commons
      │   ├── __init__.py
      │   ├── convert.py
      │   ├── page.py
      │   └── utils.py
      ├── many.py
      └── run.py
      

      image

      提示:基於from模式也可以支援 from many import *,即:匯入一個模組中所有的成員(可能會重名,所以用的少)。

    • 模組級別

      ├── commons
      │   ├── __init__.py
      │   ├── convert.py
      │   ├── page.py
      │   └── utils.py
      ├── many.py
      └── run.py
      

      image

    • 包級別

      ├── commons
      │   ├── __init__.py
      │   ├── convert.py
      │   ├── page.py
      │   ├── tencent
      │   │   ├── __init__.py
      │   │   ├── sms.py
      │   │   └── wechat.py
      │   └── utils.py
      ├── many.py
      └── run.py
      

      image

1.3 相對匯入

在匯入模組時,對於 from xx import xx這種模式,還支援相對到匯入。例如:

image

切記,相對匯入只能用在包中的py檔案中(即:巢狀在檔案中的py檔案才可以使用,專案根目錄下無法使用)。

image

1.4 匯入別名

如果專案中匯入 成員/模組/包 有重名,那麼後匯入的會覆蓋之前匯入,為了避免這種情況的發生,Python支援重新命名,即:

from xxx.xxx import xx as xo
import x1.x2 as pg

除此之外,有了as的存在,讓 import xx.xxx.xxxx.xxx 在呼叫執行時,會更加簡單(不常用,瞭解即可)。

  • 原來

    import commons.page
    
    v1 = commons.page.pagination()
    
  • 現在

    import commons.page as pg
    
    v1 = pg.pagination()
    

1.5 主檔案

  • 執行一個py檔案時

    __name__ = "__main__"
    
  • 匯入一個py檔案時

    __name__ = "模組名"
    

主檔案,其實就是在程式執行的入口檔案,例如:

├── commons
│   ├── __init__.py
│   ├── convert.py
│   ├── page.py
│   ├── tencent
│   │   ├── __init__.py
│   │   ├── sms.py
│   │   └── wechat.py
│   └── utils.py
├── many.py
└── run.py

我們通常是執行 run.py 去執行程式,其他的py檔案都是一些功能程式碼。當我們去執行一個檔案時,檔案內部的 __name__變數的值為 __main__,所以,主檔案經常會看到:

import many
from commons import page
from commons import utils


def start():
    v1 = many.show()
    v2 = page.pagination()
    v3 = utils.encrypt()


if __name__ == '__main__':
    start()

只有是以主檔案的形式執行此指令碼時start函式才會執行,被匯入時則不會被執行。

小結

  1. 模組和包的區別

  2. 匯入模組的兩種方式:

    import xx
    from xxx import xxx
    
  3. 相對匯入,需要有包名稱。

  4. 模組重名可以透過as取別名。

  5. 執行py檔案時,內部__name__=="__main__",匯入模組時,被匯入的模組 __name__="模組名"

  6. 在專案開發中,一般在主檔案中會寫上 main (主檔案標記,不是絕對的,因為其他檔案在開發除錯時候有時候也可能有main)。

2. 第三方模組

Python內部提供的模組有限,所以在平時在開發的過程中,經常會使用第三方模組。
而第三方模組必須要先安裝才能可以使用,下面介紹常見的3中安裝第三方模組的方式。

其實,使用第三方模組的行為就是去用別人寫好並開源出來的py程式碼,這樣自己拿來就用,不必重複造輪子了。。。。

2.1 pip(最常用)

這是Python中最最最常用的安裝第三方模組的方式。
pip其實是一個第三方模組包管理工具,預設安裝Python直譯器時自動會安裝,預設目錄:

MAC系統,即:Python安裝路徑的bin目錄下
	/Library/Frameworks/Python.framework/Versions/3.9/bin/pip3
	/Library/Frameworks/Python.framework/Versions/3.9/bin/pip3.9
	
Windows系統,即:Python安裝路徑的scripts目錄下
	C:\Python39\Scripts\pip3.exe
	C:\Python39\Scripts\pip3.9.exe

提示:為了方便在終端執行pip管理工具,我們也會把它所在的路徑新增到系統環境變數中。

pip3 install 模組名稱

如果你的電腦上某個寫情況沒有找到pip,也可以自己手動安裝:

  • 下載 get-pip.py 檔案,到任意目錄

    地址:https://bootstrap.pypa.io/get-pip.py
    
  • 開啟終端進入目錄,用Python直譯器去執行已下載的 get-pip.py檔案即刻安裝成功。
    image

使用pip去安裝第三方模組也非常簡單,只需要在自己終端執行:pip install 模組名稱 即可。
image

image

預設安裝的是最新的版本,如果想要指定版本:

pip3 install 模組名稱==版本

例如:
pip3 install django==2.2

2.1.1 pip更新

上圖的黃色字型提示:目前我電腦上的pip是20.2.3版本,最新的是 20.3.3 版本,如果想要升級為最新的版本,可以在終端執行他提示的命令:

/Library/Frameworks/Python.framework/Versions/3.9/bin/python3.9 -m pip install --upgrade pip

注意:根據自己電腦的提示命令去執行,不要用我這裡的提示命令哈。

2.1.2 豆瓣源

pip預設是去 https://pypi.org 去下載第三方模組(本質上就是別人寫好的py程式碼),國外的網站速度會比較慢,為了加速可以使用國內的豆瓣源。

  • 一次性使用

    pip3.9 install 模組名稱  -i  https://pypi.douban.com/simple/
    
  • 永久使用

    • 配置

      # 在終端執行如下命令
      pip3.9 config set global.index-url https://pypi.douban.com/simple/
      
      # 執行完成後,提示在我的本地檔案中寫入了豆瓣源,以後再透過pip去安裝第三方模組時,就會預設使用豆瓣源了。
      # 自己以後也可以開啟檔案直接修改源地址。
      Writing to /Users/wupeiqi/.config/pip/pip.conf
      
    • 使用

      pip3.9 install 模組名稱
      

寫在最後,也還有其他的源可供選擇(豆瓣應用廣泛)。

阿里雲:http://mirrors.aliyun.com/pypi/simple/
中國科技大學:https://pypi.mirrors.ustc.edu.cn/simple/ 
清華大學:https://pypi.tuna.tsinghua.edu.cn/simple/
中國科學技術大學:http://pypi.mirrors.ustc.edu.cn/simple/

2.2 原始碼

如果要安裝的模組在pypi.org中不存在 或 因特殊原因無法透過pip install 安裝時,可以直接下載原始碼,然後基於原始碼安裝,例如:

  • 下載requests原始碼(壓縮包zip、tar、tar.gz)並解壓。

    下載地址:https://pypi.org/project/requests/#files
    
  • 進入目錄

  • 執行編譯和安裝命令

    python3 setup.py build
    python3 setup.py install
    

image

image

2.3 wheel

wheel是Python的第三方模組包的檔案格式的一種,我們也可以基於wheel去安裝一些第三方模組。

  • 安裝wheel格式支援,這樣pip再安裝第三方模組時,就可以處理wheel格式的檔案了。

    pip3.9 install wheel
    
  • 下載第三方的包(wheel格式),例如:https://pypi.org/project/requests/#files

image

  • 進入下載目錄,在終端基於pip直接安裝
    image

無論透過什麼形式去安裝第三方模組,預設模組的安裝路徑在:

Max系統:
	/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages
Windows系統:
	C:\Python39\Lib\site-packages\

提醒:這個目錄在sys.path中,所以我們直接在程式碼中直接匯入下載的第三方包是沒問題的。

3.內建模組(一)

Python內建的模組有很多,我們也已經接觸了不少相關模組,接下來咱們就來做一些彙總和介紹。

內建模組有很多 & 模組中的功能也非常多,我們是沒有辦法注意全域性給大家講解,在此我會整理出專案開發最常用的來進行講解。

3.1 os

import os

# 1. 獲取當前指令碼絕對路徑
"""
abs_path = os.path.abspath(__file__)
print(abs_path)
"""

# 2. 獲取當前檔案的上級目錄
"""
base_path = os.path.dirname( os.path.dirname(路徑) )
print(base_path)
"""

# 3. 路徑拼接
"""
p1 = os.path.join(base_path, 'xx')
print(p1)

p2 = os.path.join(base_path, 'xx', 'oo', 'a1.png')
print(p2)
"""

# 4. 判斷路徑是否存在
"""
exists = os.path.exists(p1)
print(exists)
"""

# 5. 建立資料夾
"""
os.makedirs(路徑)
"""
"""
path = os.path.join(base_path, 'xx', 'oo', 'uuuu')
if not os.path.exists(path):
    os.makedirs(path)
"""

# 6. 是否是資料夾
"""
file_path = os.path.join(base_path, 'xx', 'oo', 'uuuu.png')
is_dir = os.path.isdir(file_path)
print(is_dir) # False

folder_path = os.path.join(base_path, 'xx', 'oo', 'uuuu')
is_dir = os.path.isdir(folder_path)
print(is_dir) # True

"""

# 7. 刪除檔案或資料夾
"""
os.remove("檔案路徑")
"""
"""
path = os.path.join(base_path, 'xx')
shutil.rmtree(path)
"""

  • listdir,檢視目錄下所有的檔案
  • walk,檢視目錄下所有的檔案(含子孫檔案)
import os

"""
data = os.listdir("xxxxxxxx")
print(data)
# ['convert.py', '__init__.py', 'page.py', '__pycache__', 'utils.py', 'tencent']
"""

"""
要遍歷一個資料夾下的所有檔案,例如:遍歷資料夾下的所有mp4檔案
"""

data = os.walk("xxxxxxx")
for path, folder_list, file_list in data:
    for file_name in file_list:
        file_abs_path = os.path.join(path, file_name)
        ext = file_abs_path.rsplit(".",1)[-1]
        if ext == "mp4":
            print(file_abs_path)

3.2 shutil

import shutil

# 1. 刪除資料夾
"""
path = os.path.join(base_path, 'xx')
shutil.rmtree(path)
"""

# 2. 複製資料夾
"""
shutil.copytree("xxxxx","xxxx")
"""

# 3.複製檔案
"""
shutil.copy("xxxx","xxxxx")
shutil.copy("xxxxx","xxxx")
"""

# 4.檔案或資料夾重新命名
"""
shutil.move("xxxx.png","x.png")
shutil.move("/files","/images")
"""

# 5. 壓縮檔案
"""
# base_name,壓縮後的壓縮包檔案
# format,壓縮的格式,例如:"zip", "tar", "gztar", "bztar", or "xztar".
# root_dir,要壓縮的資料夾路徑
"""
# shutil.make_archive(base_name=r'datafile',format='zip',root_dir=r'files')


# 6. 解壓檔案
"""
# filename,要解壓的壓縮包檔案
# extract_dir,解壓的路徑
# format,壓縮檔案格式
"""
# shutil.unpack_archive(filename=r'datafile.zip', extract_dir=r'xxxxxx/xo', format='zip')

3.3 sys

import sys

# 1. 獲取直譯器版本
"""
print(sys.version)
print(sys.version_info)
print(sys.version_info.major, sys.version_info.minor, sys.version_info.micro)
"""

# 2. 匯入模組路徑
"""
print(sys.path)
"""

  • argv,執行指令碼時,python直譯器後面傳入的引數
import sys

print(sys.argv)


# [
#       'xxxxx/2.接受執行指令碼的引數.py'
# ]

# [
#     "2.接受執行指令碼的引數.py"
# ]

# ['2.接受執行指令碼的引數.py', '127', '999', '666', 'wupeiqi']

# 例如,請實現下載圖片的一個工具。

def download_image(url):
    print("下載圖片", url)


def run():
    # 接受使用者傳入的引數
    url_list = sys.argv[1:]
    for url in url_list:
        download_image(url)


if __name__ == '__main__':
    run()

3.4 random

import random

# 1. 獲取範圍內的隨機整數
v = random.randint(10, 20)
print(v)

# 2. 獲取範圍內的隨機小數
v = random.uniform(1, 10)
print(v)

# 3. 隨機抽取一個元素
v = random.choice([11, 22, 33, 44, 55])
print(v)

# 4. 隨機抽取多個元素
v = random.sample([11, 22, 33, 44, 55], 3)
print(v)

# 5. 打亂順序
data = [1, 2, 3, 4, 5, 6, 7, 8, 9]
random.shuffle(data)
print(data)

3.5 hashlib

import hashlib

hash_object = hashlib.md5()
hash_object.update("武沛齊".encode('utf-8'))
result = hash_object.hexdigest()
print(result)
import hashlib

hash_object = hashlib.md5("iajfsdunjaksdjfasdfasdf".encode('utf-8'))
hash_object.update("武沛齊".encode('utf-8'))
result = hash_object.hexdigest()
print(result)

3.6 configparser

見:day06

3.7 xml

見:day06

總結

  1. 模組和包的區別

  2. 瞭解如何匯入模組

    • 路徑
    • 匯入方式
  3. 匯入模組時一般要遵循的規範【補充】

    • 註釋:檔案頂部或init檔案中。

    • 在檔案頂部匯入

    • 有規則匯入,並用空行分割。

      # 先內建模組
      
      # 再第三方模組
      
      # 最後自定義模組
      
      import os
      import sys
      import random
      import hashlib
      
      import requests
      import openpyxl
      
      from commons.utils import encrypt
      
  4. 第三方模組安裝的方法

  5. 常見內建模組

作業

  1. 自己去網上搜尋如何基於Python計算mp4影片的時長,最終實現用程式碼統計某個資料夾下所有mp4的時長。
from moviepy.editor import VideoFileClip
import os


# 遍歷目錄下的所有mp4
def get_mp4_hour(file_path):
    total_seconds = 0
    data = os.walk(file_path)
    for path, folder_list, file_list in data:
        for file_name in file_list:
            file_abs_path = os.path.join(path, file_name)
            ext = file_abs_path.rsplit(".", 1)[-1]
            if ext == "mp4":
                clip = VideoFileClip(file_abs_path)
                duration = clip.duration
                total_seconds += duration

    hour = round(total_seconds/60/60, 2)
    return hour


if __name__ == '__main__':
    get_mp4_hour("xxxx")

相關文章