天天看點

python基礎Ⅳ(檔案操作、子產品和包導入、os子產品、自定義子產品釋出與安裝、sys子產品、time子產品、datetime子產品、random子產品、hashlib子產品)一、檔案操作二、子產品和包導入三、os子產品四、自定義子產品釋出與安裝五、sys子產品六、time子產品七、datetime子產品八、random子產品九、hashlib子產品

一、檔案操作

打開檔案

用于打開一個檔案,建立并傳回一個 file 對象

open(name[, mode[, buffering]])
  • name : 檔案名稱的字元串值。
  • mode : 打開檔案的模式:隻讀,寫入,追加等。這個參數是非強制的,預設檔案通路模式為隻讀。
  • buffering : 如果 buffering 的值被設為 0,就不會有寄存。如果 buffering 的值取 1,通路檔案時會寄存行。如果将 buffering 的值設為大于 1 的整數,表明了這就是的寄存區的緩沖大小。如果取負值,寄存區的緩沖大小則為系統預設。
模式 說明
b 二進制模式 (文本檔案、視訊、音樂等等都可使用該模式) 。
+ 打開一個檔案進行更新 (可讀可寫)。
r 以隻讀方式打開檔案。檔案的指針将會放在檔案的開頭。這是預設模式。
w 打開一個檔案隻用于寫入。如果該檔案已存在則打開檔案,并從開頭開始編輯,即原有内容會被删除。如果該檔案不存在,建立新檔案。
a 打開一個檔案用于追加。如果該檔案已存在,檔案指針将會放在檔案的結尾。如果該檔案不存在,建立新檔案進行寫入
r+ 打開一個檔案用于讀寫。檔案指針将會放在檔案的開頭。不能建立檔案,注意指針的位置
w+ 打開一個檔案用于讀寫。如果該檔案已存在則打開檔案,并删除原來内容,然後在進行讀寫,注意指針的位置。如果該檔案不存在,建立新檔案。
rb+ 以二進制格式打開一個檔案用于讀寫。檔案指針将會放在檔案的開頭,注意指針的位置。
wb+ 以二進制格式打開一個檔案用于讀寫。如果該檔案已存在則打開檔案,并從開頭開始編輯,即原有内容會被删除,注意指針的位置。如果該檔案不存在,建立新檔案。
  • 要注意的是python3的檔案預設編碼為utf-8,但檔案讀和寫(r|w)的預設編碼為gbk
  • 一個我們可讀的txt文本包括兩個重要部分,一個是文字的編碼格式,另一個是文本的讀取格式。這兩個要一緻才可以把二進制翻譯成我們可讀的txt檔案
  • 文本檔案才存在行的概念,二進制檔案不存在
  • 之是以存在要注意檔案的指向的問題是因為檔案的讀取在python3裡面是以流的形式的
  • 要注意open() 裡面的encoding預設為gbk,encode() 方法裡面的 encoding 預設為utf-8

write()

file_obj = open('./test.txt', 'w', encoding='utf-8')	# 打開檔案,并把字元的編碼與檔案的編碼方式換為utf-8,預設為gbk
file_obj.write('你好\n')			# 預設的編碼為gbk,在這裡是utf-8
file_obj.write('世界\n')
file_obj.close()				# 注意要關閉檔案,以對檔案進行保護
           
file_obj = open('./test.txt', 'wb+')

file_obj.write('sss你好,撒大大青蛙的'.encode('utf-8'))	# 以utf-8編碼對字元串進行編碼,獲得bytes類型對象
file_obj.close()
           

①file.read([size]):size指定的話則傳回指定字元個數, 未指定則傳回整個檔案,f.read()讀到檔案尾時傳回""(空字串),且換行符也算字元,注意檔案指針的指向

②file.readline():傳回一行,且這行裡面末尾會自動加上換行符(\n),注意檔案指針的指向

③file.readlines([size]) :傳回包含size行的清單, size 未指定則傳回全部行,注意檔案指針的指向

④file.readable():判斷file對象是否可讀,當然對應的也有writable()函數

with上文管理

with 語句适用于對資源進行通路的場合,確定不管使用過程中是否發生異常都會執行必要的“清理”操作,釋放資源,比如檔案使用後自動關閉、線程中鎖的自動擷取和釋放等。

with open('./test.txt', 'r', encoding='utf-8') as file_obj:
    print(file_obj.read())
           

f.close()

關閉檔案流通道

檔案備份

# 适用于小檔案

def copyFile(param):
    file_list = param.split('.')
    new_file = './' + file_list[0] + '_copy.' + file_list[1]
    old_file_obj = open(param, 'r', encoding='utf-8')
    new_file_obj = open(new_file, 'w', encoding='utf-8')
    new_file_obj.write(old_file_obj.read())
    old_file_obj.close()
    new_file_obj.close()
    pass

copyFile('test.txt')
           
# 适用于大檔案

def copyFile(param):
    file_list = param.split('.')
    new_file = './' + file_list[0] + '_copy.' + file_list[1]
    try:
        with open(param, 'r', encoding='utf-8') as old_file_obj, open(new_file, 'w', encoding='utf-8') as new_file_obj:
            while True:
                str_current = old_file_obj.read(1024)
                new_file_obj.write(str_current)
                if len(str_current) < 1024:
                    break
                    pass
                pass
            old_file_obj.close()
            new_file_obj.close()
            pass
        pass
    except Exception as msg:
        print(msg)
        pass
    else:
        print('複制成功')
        pass
    pass

copyFile('test.txt')
           

檔案讀取定位

tell()可以獲得目前檔案指針讀取到的位元組位置,不過要注意一個漢字對應兩個位元組

file_obj = open('./test.txt', 'w', encoding='utf-8')	
file_obj.write('888 ni 你好')			# 12個位元組
print(file_obj.tell())

file_obj.close()
           

truncate()

截取檔案内的指定字元

file_obj = open('./test.txt', 'r+', encoding='utf-8')
file_obj.truncate(3)		# 截取檔案前三個字元
print(file_obj.read())		# 讀取檔案
file_obj.close()
           

seek()

用于移動檔案指針到指定位置

fileObject.seek(offset[, whence])
  • offset – 偏移量,也就是代表需要移動偏移的位元組數
  • whence:可選,預設值為 0。給offset參數一個定義,表示要從哪個位置開始偏移;0代表從檔案開頭開始算起,1代表從目前位置開始算起,2代表從檔案末尾算起。
with open('./test.txt', 'rb') as file_obj:		# with塊
	file_obj.seek(2, 0)
    print(file_obj.read(4).decode('gbk'))		# 把讀取的二進制使用gbk編碼來解釋
    print(file_obj.tell())				# 獲得目前的指針位置
    file_obj.seek(-2, 1)				# 報錯,不可這樣使用
    print(file_obj.read(2).decode('gbk'))
    file_obj.seek(-2, 2)				# 報錯
    print(file_obj.read(2).decode('gbk'))

    pass
           

注意:若沒有使用二進制讀寫檔案,則seek函數裡面的whence隻能為0,而其他情況會報錯

例如:

with open('./test.txt', 'r') as file_obj: 		# r模式
    file_obj.seek(2, 0)				# 可以執行
    print(file_obj.read(2))
    print(file_obj.tell())
    
    file_obj.seek(-2, 1)				# 報錯
    print(file_obj.read(2))
    
    file_obj.seek(-2, 2)				# 報錯
    print(file_obj.read(2))
    pass


with open('./test.txt', 'w') as file_obj:		# w模式
    file_obj.seek(2, 0)				# 可以執行
    file_obj.write('11')
    file_obj.seek(-2, 1)				# 報錯
    file_obj.write('11')
    file_obj.seek(-2, 2)				# 報錯
    file_obj.write('11')

    pass

           

二、子產品和包導入

子產品和包的導入

  • 導入一般放在檔案最前面
  • from……import…… 就隻導入該子產品或包中的部分内容或全部内容(*),要注意的是該方式在調用時隻能使用預設名,就可能會造成命名沖突
  • 要注意無論使用何種方式導入子產品,導入子產品的全部内容都會被執行。且在通過包導入子產品時候會執行該子產品和__init__子產品
  • 在隻導入包時隻會執行__init__子產品,也就意味着無法通路除__init__子產品的其他子產品
  • 在一次程式執行中,對相同的内容import導入就隻導入一次
import time
print(time.ctime())

from time import ctime			# 推薦使用
print(time.ctime())

from user.models import User	# user為包名,models為子產品名,User為子產品内的東西
           

as為子產品取别名

注意這裡是子產品名,而不是函數名

import time as myTime
print(myTime.ctime())
           

__name__

python的子產品既可以被調用,也可以獨立運作。而被調用時__name__存儲的是py檔案名(子產品名稱),獨立運作時存儲的是"__main__"。

__all__

它表示一個子產品中允許哪些屬性可以被導入到别的子產品中(如:全局變量,函數,類),是以它是為了限制或者指定能被導入到别的子產品的函數,類,全局變量等,如果指定了那麼隻能是指定的那些可以被導入,沒有指定預設就是全部可以導入。

但需要注意的是__all__隻影響到了 from <module> import * 這種導入方式,對于 from <module> import <member> 導入和import <module>方式并沒有影響,仍然可以從外部導入。

子產品搜尋路徑

當解釋器遇到import關鍵字,會優先搜尋目前錄下是否有這個名字的子產品,是以在子產品命名的時候不要與系統中的子產品有重名(自定義的檔案優先級高);如果目前目錄沒有,則到環境變量中搜尋;如果都找不到,則搜尋預設路徑,window的第三方子產品安裝位置在python安裝目錄下的lib/site-packages/目錄下。

包和檔案夾

  • 包和檔案夾差異不大,隻是包内有一個__init__.py檔案。也就是說如果在檔案夾裡面定義一個__init__.py檔案檔案夾就變成了一個包
  • 一個項目裡可有多個包,一個包裡面可以放多個子產品

包的__init__.py檔案

  • __init__子產品會在導入包時自動執行,該子產品裡面一般放一些初始化函數、變量等等,而函數、變量等可通過包名來調用。
  • 它也可配合__all__來使用

子產品的循環導入問題

大型的python項目中,需要很多python檔案,由于架構不當,可能會出現子產品之間的互相導入,而嚴重的會導緻程式崩潰。不過有兩種避免方法:①重新架構,代價太大②将導入的語句放到調用的地方以避免導緻程式崩潰③使用__name__ 以避免程式邏輯混亂

例如1(下面的程式因循環導入子產品而導緻程式崩潰):

# 該檔案為index.py
from hello import foo1
def foo():
    print('index---- foo')


# 該檔案為hello.py,且為入口檔案
from index import foo
def foo1():
    print('hello---- foo1')
foo1()


# 輸出結果
ImportError: cannot import name 'foo' from partially initialized module 'index' (most likely due to a circular import)
           

下面為解決方法:

# 該檔案為index.py
def foo():
	from hello import foo1
    print('index---- foo')


# 該檔案為hello.py,且為入口檔案
from index import foo
def foo1():
    print('hello---- foo1')
foo1()


# 輸出結果
hello---- foo1
           

例如2(下面的程式因多次導入子產品而導緻程式邏輯混亂):

# 該檔案為index.py
def foo():
    print('index---- foo')
    from hello import foo1
    foo1()


# 該檔案為hello.py,且為入口檔案
from index import foo
def foo1():
    print('hello---- foo1')
def foo2():
    print('hello---- foo2')
    foo()
foo1()
foo2()


# 輸出結果
hello---- foo1
hello---- foo2
index---- foo
hello---- foo1
hello---- foo2
index---- foo
hello---- foo1
hello---- foo1
           

下面為解決方法:

# 該檔案為index.py
def foo():
    print('index---- foo')
    from hello import foo1
    foo1()


# 該檔案為hello.py,且為入口檔案
from index import foo
def foo1():
    print('hello---- foo1')
def foo2():
    print('hello---- foo2')
    foo()
if __name__ == '__main__':			# 防止循環導入子產品
    foo1()
    foo2()


# 輸出結果
hello---- foo1
hello---- foo2
index---- foo
hello---- foo1
           

三、os子產品

os子產品是提供一些系統級别的操作指令(如:檔案重命名等),下面介紹一些常用的方法

路徑操作

os.path.isabs()

判斷路徑是否為絕對路徑

import os

print(os.path.isabs(r'C:\Users\12133\Documents\WindowsPowerShell'))		# True
           

os.path.dirname()

它與getcwd函數類似,獲得傳入參數的上級目錄,__file__的值為目前檔案的絕對路徑

import os

print(os.path.dirname(__file__))	# 這裡輸出的結果為目前檔案的工作目錄
print(__file__)

# 輸出結果
F:\pycharm\pythonProject
F:\pycharm\pythonProject\index.py
           

os.getcwd()

用于傳回目前檔案的上級目錄,沒有參數

import os
print(os.getcwd())			# F:\pycharm\pythonProject
           

os.path.abspath()

将傳入的路徑轉換為絕對路徑

import os

print(os.path.abspath('./index.py'))

# 輸出結果
F:\pycharm\pythonProject\index.py
           

os.path.join()

路徑拼接,用于将多個路徑組合後傳回

import os
path = os.path.join(os.getcwd(), 'hello.txt')	# 目錄的拼接,注意這裡是path下面的join
print(path)
           

os.path.split()

路徑分割獲得檔案名,用于将一個路徑分割并組成一個元組後再傳回

import os
print(os.path.split(r'./index.py'))
print(os.path.split(r'F:\pycharm\pythonProject/index.py'))
# 輸出結果
('.', 'index.py')
('F:\\pycharm\\pythonProject', 'index.py')
           

os.path.splitext()

路徑分割獲得檔案拓展名,用于将一個路徑分割并組成一個元組後再傳回

import os
print(os.path.splitext(r'./index.py'))
print(os.path.splitext(r'F:\pycharm\pythonProject/index.py'))
# 輸出結果
('./index', '.py')
('F:\\pycharm\\pythonProject/index', '.py')
           

os.path.isdir()&os.path.isfile()

判斷是否是目錄或檔案

import os

with os.scandir('./') as entries:			# 使用with來處理資源通路操作
    for entry in entries:
        if os.path.isdir(entry):			# 判斷是否為檔案夾
            print('檔案夾名:{}'.format(entry))
            pass
        elif os.path.isfile(entry):			# 判斷是否為檔案
            print('檔案名:{}'.format(entry))
        pass

           

檔案操作

os.rename()

修改檔案名

import os
os.rename( 'test.txt' , 'tests.txt')
           

os.remove()

删除檔案

import os
os.remove( 'tests.txt ')
           

os.mkdir()

建立檔案夾

import os
os.mkdir('myTest')			# 它隻能建立一級目錄
os.makedirs('d:/myTest/test')			# 它可以建立多級目錄
           

os.rename()&shutil.rmtree()

删除檔案夾,os.rename()隻能删除空檔案夾,shutil.rmtree()用于删除多級檔案夾

import os
os.rmdir('myTest')				# 隻能删除空目錄

import shutil
shutil.rmtree('d:/myTest')		# 删除多級目錄
           

os.chdir()

切換目錄

import os
os.chdir('./venv')				# 切換目錄
print(os.getcwd())
           

os.listdir()&os.scandir()

傳回目錄所在的檔案或檔案夾清單,隻傳回一級目錄

import os
print(os.listdir('./'))			# 隻列印一級,且傳回一個清單

print(os.scandir('./'))			# 傳回一個疊代器對象
with os.scandir('./') as fileValue:	# with盡量與資源通路一起使用
    for value in fileValue:
        print(value)			# 隻列印一級對象
        pass
    pass
           

四、自定義子產品釋出與安裝

在python裡面,一個子產品就是一個python檔案。

自定義子產品釋出

需要釋出的子產品(simpleCompute.py):

def addition(x, y):
    return x + y


def minus(x, y):
    return x - y


className = '一班'

__all__ = ['addition', 'className']

if __name__ == '__main__':			# 測試時執行
    print('這裡是測試用例')
    print('__name__值為%s' % __name__)
    pass

           

若要釋出子產品的話,要先建立一個檔案夾,再把寫好的子產品放入到檔案夾内,然後再在該檔案夾内建立一個setup.py檔案,内容如下,然後再在終端内進入該檔案夾目錄内,輸入python setup.py build(構模組化塊),然後會在該檔案夾内生成一個build檔案夾,再在該檔案夾内輸入python setup.py sdist,來生成壓縮包并會在該檔案夾内生成一個dist檔案夾。

當然我們也可使用在該檔案内輸入tree指令來檢視這個檔案的目錄結構

setup.py檔案:

from distutils.core import setup
# name子產品名稱
# version版本号
# description 描述
# author作者
# py_modules要釋出的内容
setup(name="simpleCompute", version="1.0", description=”檔案的簡單計算子產品"", autbor="xMan", py_modules=['simpleCompute'])
           

自定義子產品安裝

在pycharm裡面的終端裡面輸入pip install 壓縮檔案即可安裝子產品

pip install simpleCompute-1.0.tar.gz
           

五、sys子產品

sys子產品為python環境子產品

sys.path

導入包的搜尋路徑

import sys

print(sys.path)
# 輸出結果
['F:\\pycharm\\pythonProject', 'F:\\pycharm\\pythonProject', 'F:\\pycharm\\PyCharm 2020.2.3\\plugins\\python\\helpers\\pycharm_display', 'F:\\python\\python39.zip', 'F:\\python\\DLLs', 'F:\\python\\lib', 'F:\\python', 'F:\\pycharm\\pythonProject\\venv', 'F:\\pycharm\\pythonProject\\venv\\lib\\site-packages', 'F:\\pycharm\\PyCharm 2020.2.3\\plugins\\python\\helpers\\pycharm_matplotlib_backend']
           

sys.version

import sys

print(sys.version)
# 輸出結果
3.9.0 (tags/v3.9.0:9cf6752, Oct  5 2020, 15:34:40) [MSC v.1927 64 bit (AMD64)]
           

六、time子產品

time()

傳回目前的時間戳(秒),浮點類型

import time

print(time.time())
# 輸出結果
1606561264.2610068
           

sleep()

休眠一段時間

import time

print(time.time())
time.sleep(3)
print(time.time())
# 輸出結果
1606561596.5063899
1606561599.5070715
           

ctime()

若有參數(時間戳)則把參數轉成字元串(該格式無法修改),若無參數則傳回目前日期(字元串類型)

import time

second = time.time()
print(time.ctime(second))
print(time.ctime())
# 輸出結果
Sat Nov 28 19:09:59 2020
Sat Nov 28 19:09:59 2020
           

strptime()

time.strptime(string, format)

将字元串轉換為元組類型

import time

print(time.strptime('2020年10月19日', '%Y年%m月%d日'))
# 輸出結果
time.struct_time(tm_year=2020, tm_mon=10, tm_mday=19, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=0, tm_yday=293, tm_isdst=-1)
           

localtime()

time.localtime([ sec ])

若有參數(時間戳)則把參數轉成元組時間,若無參數則傳回目前日期(元組類型)

import time

second = time.time()
print(time.localtime(second))		# 
print(time.localtime())
# 輸出結果
time.struct_time(tm_year=2020, tm_mon=11, tm_mday=28, tm_hour=19, tm_min=12, tm_sec=11, tm_wday=5, tm_yday=333, tm_isdst=0)
time.struct_time(tm_year=2020, tm_mon=11, tm_mday=28, tm_hour=19, tm_min=12, tm_sec=11, tm_wday=5, tm_yday=333, tm_isdst=0)
           

mktime()

将元組時間轉換為時間戳(浮點型)

import time

time_tuple = time.localtime()
print(time.mktime(time_tuple))
# 輸出結果
1606562577.0
           

strftime()

time.strftime(format[, t])

将元組時間轉成字元串(該格式可以自定義)

import time

time_tuple = time.localtime()
print(time.strftime('%Y年%m月%d日'))
print(time.strftime('%Y年%m月%d日', time_tuple))
# 輸出結果
2020年11月28日
2020年11月28日
           

下面的圖為有參數的各種函數轉換情況(若沒有參數則直接獲得目前的時間)

python基礎Ⅳ(檔案操作、子產品和包導入、os子產品、自定義子產品釋出與安裝、sys子產品、time子產品、datetime子產品、random子產品、hashlib子產品)一、檔案操作二、子產品和包導入三、os子產品四、自定義子產品釋出與安裝五、sys子產品六、time子產品七、datetime子產品八、random子產品九、hashlib子產品

七、datetime子產品

datetime 比 time 進階了不少,可以了解為 datetime 基于 time 進行了封裝,提供了更多實用的函數

datetime.now()

傳回目前時間

import datetime

now = datetime.datetime.now()
print(now)
# 輸出結果
2020-11-28 20:15:44.940523
           

timedelta()

timedelta(Δ)可以友善實作日期(date執行個體、time執行個體、datetime執行個體)之間的運算。

import datetime

timedel = datetime.timedelta(days=2)
print(timedel)			# 時間間隔
now = datetime.datetime.now()
print(now)			# 輸出目前時間
print(now + timedel)	# 輸出經處理的時間
# 輸出結果
2 days, 0:00:00
2020-11-28 20:09:47.057137
2020-11-30 20:09:47.057137
           

八、random子產品

random()

傳回一個0到1的小數

import random

print(random.random())
# 輸出結果
0.7519760407323736
           

randint()

傳回一個整數,包含邊界

import random

print(random.randint(1, 3))
           

choice()

random.choice(sequence)

随機選擇序列裡的某個值(抓阄)

import random

list1 = ['mike', 'li', 'hua', 'ming', 'wang']
print(random.choice(list1))
# 輸出結果
li
           

shuffle()

random.shuffle (list)

将清單裡的值順序打亂,沒有傳回值(洗牌)

import random

list1 = ['mike', 'li', 'hua', 'ming', 'wang']
random.shuffle(list1)
print(list1)
# 輸出結果
['mike', 'wang', 'ming', 'hua', 'li']
           

九、hashlib子產品

hashlib子產品提供一些加密的算法

md5()

import hashlib

str1 = 'li,你好嗎?'
md5 = hashlib.md5(str1.encode('utf-8'))	# 注意這裡的編碼格式
print(md5.hexdigest())			# 将加密結果以十六進制的方式輸出
print(md5)
# 輸出結果
3f413c7523a0bad284c6e5b84e2dc0fb
<md5 _hashlib.HASH object @ 0x000001DAA0652B50>
           

本文隻用于個人學習與記錄

上一篇: extremeQoS限速
下一篇: LTE CSFB