我心中的王者:Python-第14章 文件的读取与写入

我心中的王者:Python-第14章 文件的读取与写入

本章笔者将讲解使用Python处理Windows操作系统内文件的完整相关知识,例如,文件路径的管理、文件的读取与写入、目录的管理、文件压缩与解压缩、认识编码规则与剪贴板的相关应用。

14-1 文件夹与文件路径

有一个文件路径图形如下:
在这里插入图片描述

对于ch14_1.py而言,它的文件路径名称是:

D:\Python\ch14\ch14_1.py

对于ch14_1.py而言,它的当前工作目录(也可称文件夹)名称是:

D:\Python\ch14

14-1-1 绝对路径与相对路径

在操作系统中可以使用2种方式表达文件路径,下列是以ch14_1.py为例:

绝对路径:路径从根目录开始表达,以14-1节的文件路径图为例,它的绝对路径是:

 D:\Python\ch14\ch14_1.py

相对路径:是指相对于当前工作目录的路径,以14-1节的文件路径图为例,若是当前工作目录是D:\Python\ch14,它的相对路径是:

 ch14_1.py

另外,在操作系统处理文件夹的观念中会使用2个特殊符号“.”和“…”,“.”指的是当前文件夹,“…”指的是上一层文件夹。但是在使用上,当指当前文件夹时也可以省略“.\”。所以使用“.\ch14_1.py”与“ch14_1.py”意义相同。

14-1-2 os模块与os.path模块

在Python内有关文件路径的模块是os,所以在本节实例最前面均需导入此模块。

  import os  # 导入os模块

在os模块内有另一个常用模块os.path,14-1节主要是使用这2个模块的方法,讲解与文件路径有关的文件夹知识,由于os.path是在os模块内,所以导入os模块后不用再导入os.path模块。

14-1-3 取得当前工作目录os.getcwd( )

os模块内的getcwd( )可以取得当前工作目录。

程序实例ch14_1.py:列出当前工作目录。

# ch14_1.py
import os

print(os.getcwd())              # 列出目前工作目录

执行结果
在这里插入图片描述

14-1-4 取得绝对路径os.path.abspath

os.path模块的abspath(path)会传回path的绝对路径,通常我们可以使用这个方法将文件或文件夹的相对路径转成绝对路径。

程序实例ch14_2.py:取得绝对路径的应用。

# ch14_2.py
import os

print(os.path.abspath('.'))              # 列出目前工作目录的绝对路径
print(os.path.abspath('..'))             # 列出上一层工作目录的绝对路径
print(os.path.abspath('ch14_2.py'))      # 列出目前档案的绝对路径

执行结果
在这里插入图片描述

14-1-5 传回特定路段相对路径os.path.relpath( )

os.path模块的relpath(path, start)会传回从start到path的相对路径,如果省略start,则传回当前工作目录至path的相对路径。

程序实例ch14_3.py:传回特定路段相对路径的应用。

# ch14_3.py
import os

print(os.path.relpath('D:\\'))              # 列出目前工作目录至D:\的相对路径
print(os.path.relpath('D:\\Python\\ch13'))  # 列出目前工作目录至特定path的相对路径
print(os.path.relpath('D:\\', 'ch14_3.py')) # 列出目前档案至D:\的相对路径

执行结果

在这里插入图片描述

14-1-6 检查路径方法exist/isabs/isdir/isfile

下列是常用的os.path模块方法。

exist(path):如果path的文件或文件夹存在传回True,否则传回False。

isabs(path):如果path的文件或文件夹是绝对路径传回True,否则传回False。

isdir(path):如果path是文件夹传回True,否则传回False。

isfile(path):如果path是文件传回True,否则传回False。

程序实例ch14_4.py:检查路径方法的应用。

# ch14_4.py
import os

print("档案或文件夹存在 = ", os.path.exists('ch14'))
print("档案或文件夹存在 = ", os.path.exists('D:\\Python\\ch14'))
print("档案或文件夹存在 = ", os.path.exists('ch14_4.py'))
print(" --- ")

print("是绝对路径 = ", os.path.isabs('ch14_4.py'))
print("是绝对路径 = ", os.path.isabs('D:\\Python\\ch14\\ch14_4.py'))
print(" --- ")

print("是文件夹 = ", os.path.isdir('D:\\Python\\ch14\\ch14_4.py'))
print("是文件夹 = ", os.path.isdir('D:\\Python\\ch14'))
print(" --- ")

print("是档案 = ", os.path.isfile('D:\\Python\\ch14\\ch14_4.py'))
print("是档案 = ", os.path.isfile('D:\\Python\\ch14'))

执行结果

档案或文件夹存在 =  False
档案或文件夹存在 =  False
档案或文件夹存在 =  True
 ---
是绝对路径 =  False
是绝对路径 =  True
 ---
是文件夹 =  False
是文件夹 =  False
 ---
是档案 =  False
是档案 =  False

14-1-7 文件与目录的操作mkdir/rmdir/remove/chdir

这几个方法是在os模块内,建议执行下列操作前先用os.path.exists( )检查是否存在。

mkdir(path):建立path目录。

rmdir(path):删除path目录,限制只能是空的目录。如果要删除底下有文件的目录需参考14-4-7小节。

remove(path):删除path文件。

chdir(path):将当前工作文件夹改至path。

程序实例ch14_5.py:使用mkdir建立文件夹的应用。

# ch14_5.py
import os

mydir = 'testch14'
# 如果mydir不存在就建立此文件夹
if os.path.exists(mydir):
    print("已经存在 %s " % mydir)
else:
    os.mkdir(mydir)
    print("建立 %s 文件夹成功" % mydir)

执行结果

建立 testch14 文件夹成功
已经存在 testch14 

下列是验证testch14建立成功的画面。
在这里插入图片描述

程序实例ch14_6.py:使用rmdir删除文件夹的应用。

# ch14_6.py
import os

mydir = 'testch14'
# 如果mydir存在就删除此文件夹
if os.path.exists(mydir):
    os.rmdir(mydir)
    print("删除 %s 文件夹成功" % mydir)
else:
    print("%s 文件夹不存在" % mydir)

执行结果

删除 testch14 文件夹成功

下列是验证testch14已经删除的画面。
在这里插入图片描述

程序实例ch14_7.py:删除指定path文件的应用。

# ch14_7.py
import os

myfile = 'test.py'
# 如果myfile存在就删除此档案
if os.path.exists(myfile):
    os.remove(myfile)
    print("删除 %s 档案成功" % myfile)
else:
    print("%s 档案不存在" % myfile)

执行结果 下列分别是删除文件不存在(左边)或存在(右边)的执行结果画面。
在这里插入图片描述

程序实例ch14_8.py:更改当前工作文件夹,然后再返回原先工作文件夹。

# ch14_8.py
import os

newdir = 'D:\\Python'
currentdir = os.getcwd()
print("列出目前工作文件夹 ", currentdir)

# 如果newdir不存在就建立此文件夹
if os.path.exists(newdir):
    print("已经存在 %s " % newdir)
else:
    os.mkdir(newdir)
    print("建立 %s 文件夹成功" % newdir)

# 将目前工作文件夹改至newdir
os.chdir(newdir)
print("列出最新工作文件夹 ", os.getcwd())

# 将目前工作文件夹返回
os.chdir(currentdir)
print("列出返回工作文件夹 ", currentdir)

执行结果
在这里插入图片描述

14-1-8 传回文件路径os.path.join( )

这个方法可以将os.path.join( )参数内的字符串结合为一个文件路径,参数可以有2个到多个。

程序实例ch14_9.py:os.path.join( )方法的应用,这个程序会用2、3、4个参数测试这个方法。

# ch14_9.py
import os

print(os.path.join('D:\\', 'Python', 'ch14', 'ch14_9.py'))   # 4个参数
print(os.path.join('D:\\Python', 'ch14', 'ch14_9.py'))       # 3个参数
print(os.path.join('D:\\Python\\ch14', 'ch14_9.py'))         # 2个参数

执行结果

D:\Python\ch14\ch14_9.py
D:\Python\ch14\ch14_9.py
D:\Python\ch14\ch14_9.py

程序实例ch14_10.py:使用for循环将一个列表内的文件与一个路径结合。

# ch14_10.py
import os

files = ['ch14_1.py', 'ch14_2.py', 'ch14_3.py']
for file in files:
    print(os.path.join('D:\\Python\\ch14', file))   

执行结果

D:\Python\ch14\ch14_1.py
D:\Python\ch14\ch14_2.py
D:\Python\ch14\ch14_3.py

14-1-9 获得特定文件的大小os.path.getsize( )

这个方法可以获得特定文件的大小。

程序实例ch14_11.py:获得ch14_1.py的文件大小,从执行结果可以知道是90字节。

# ch14_11.py
import os

# 如果档案在目前工作目录下可以省略路径
print(os.path.getsize("ch14_1.py"))
print(os.path.getsize("D:\\Python\\ch14\\ch14_1.py"))

执行结果
在这里插入图片描述

下列是验证结果。
在这里插入图片描述

14-1-10 获得特定工作目录的内容os.listdir( )

这个方法将以列表方式列出特定工作目录的内容。

程序实例ch14_12.py:以两种方式列出D:\Python\ch14的工作目录内容。

# ch14_12.py
import os

print(os.listdir("D:\\Python\\ch14"))
print(os.listdir("."))                  # 这代表目前工作目录

执行结果
在这里插入图片描述

程序实例ch14_13.py:列出特定工作目录所有文件的大小。

# ch14_13.py
import os

totalsizes = 0
print("列出D:\\Python\\ch14工作目录的所有档案")
for file in os.listdir('D:\\Python\\ch14'):
    print(file)
    totalsizes += os.path.getsize(os.path.join('D:\\Python\\ch14', file))

print("全部档案大小是 = ", totalsizes)

执行结果
在这里插入图片描述

14-1-11 获得特定工作目录内容glob

Python内还有一个模块可用于列出特定工作目录内容glob,当导入这个模块后可以使用glob方法获得特定工作目录的内容,这个方法最大特色是可以使用通配符“”,例如,可用“.txt”获得所有txt扩展名的文件,更多应用可参考下列实例。

程序实例ch14_14.py:方法1是列出所有工作目录的文件,方法2是列出ch14_1开头的扩展名是py的文件,方法3是列出ch14_2开头的所有文件。

# ch14_14.py
import glob

print("方法1:列出\\Python\\ch14工作目录的所有档案")
for file in glob.glob('D:\\Python\\ch14\*.*'):
    print(file)
    
print("方法2:列出目前工作目录的特定档案")
for file in glob.glob('ch14_1*.py'):
    print(file)
    
print("方法3:列出目前工作目录的特定档案")
for file in glob.glob('ch14_2*.*'):
    print(file)


执行结果

方法1:列出\Python\ch14工作目录的所有档案
方法2:列出目前工作目录的特定档案
ch14_1.py
ch14_10.py
ch14_11.py
ch14_12.py
ch14_13.py
ch14_14.py
ch14_14_1.py
ch14_15.py
ch14_16.py
ch14_17.py
ch14_18.py
ch14_19.py
方法3:列出目前工作目录的特定档案
ch14_2.py
ch14_20.py
ch14_20.txt
ch14_21.py
ch14_22.py
ch14_23.py
ch14_24.py
ch14_25.py
ch14_26.py
ch14_27.py
ch14_28.py
ch14_29.py

14-1-12 遍历目录树os.walk( )

在os模块内有提供一个os.walk( )方法可以让我们遍历目录树,这个方法每次执行循环时将传回3个值:

①当前工作目录名称(dirName)。

②当前工作目录底下的子目录列表(sub_dirNames)。

③当前工作目录底下的文件列表(fileNames)。

下列是语法格式:

for dirName, sub_dirNames,fileNames in os.walk(目录路径):
程序区块

上述dirName, sub_dirNames, fileNames名称可以自行命名,顺序则不可以更改,至于目录路径可以使用绝对地址或相对地址,如果不注明则代表当前工作目录的子目录。

程序实例ch14_14_1.py:在笔者范例D:\Python\ch14目录下列有一个oswalk目录,此目录内容如下:
在这里插入图片描述

本程序将遍历此oswalk目录,同时列出内容。

# ch14_14_1.py
import os

for dirName, sub_dirNames, fileNames in os.walk('oswalk'):
    print("目前工作目录名称:   ", dirName)
    print("目前子目录名称列表: ", sub_dirNames)
    print("目前文件名列表:   ", fileNames, "\n")

执行结果

目前工作目录名称:    oswalk
目前子目录名称列表:  ['mydir', 'mytest']
目前文件名列表:    ['data1.txt']

目前工作目录名称:    oswalk\mydir
目前子目录名称列表:  ['mysubdir']
目前文件名列表:    ['data2.txt', 'data3.txt']

目前工作目录名称:    oswalk\mydir\mysubdir
目前子目录名称列表:  []
目前文件名列表:    ['data6.txt']

目前工作目录名称:    oswalk\mytest
目前子目录名称列表:  []

从上述执行结果可以看到,os.walk( )将遍历指定目录底下的子目录同时传回子目录列表和文件列表,如果所传回的子目录列表是[ ]代表底下没有子目录。

14-2 读取文件

Python处理读取或写入文件首先需将文件打开,然后可以一次读取所有文件内容或是一行一行读取文件内容。Python可以使用open( )函数打开文件,文件打开后会传回文件对象,未来可用读取此文件对象方式读取文件内容,更多有关open( )函数可参考4-3-1小节。

14-2-1 读取整个文件read( )

文件打开后,可以使用read( )读取所打开的文件,使用read( )读取时,所有的文件内容将以一个字符串方式被读取然后存入字符串变量内,未来只要打印此字符串变量相当于可以打印整个文件内容。

在本书ch14文件夹有ch14_15.txt文件。

程序实例ch14_15.py:读取ch14_15.txt文件然后输出,请读者留意程序第5行,笔者使用打印一般变量方式就打印了整个文件了。
在这里插入图片描述

# ch14_15.py

fn = 'ch14_15.txt'          # 设定欲开启的档案
file_Obj =  open(fn)        # 用预设mode=r开启档案,传回调案对象file_Obj
data = file_Obj.read()      # 读取档案到变量data
file_Obj.close()            # 关闭档案对象
print(data)                 # 输出变量data相当于输出档案

执行结果

深石数位
深度学习滴水穿石
Deep Learning

上述使用open( )打开文件时,建议使用close( )将文件关闭可参考第6行,若是没有关闭也许未来文件内容会有不可预期的损害。

另外,上述程序第3和4行所打开的文件ch14_15.txt没有文件路径,这表示这个文件需与程序文件在相同的工作目录,否则会有找不到这个文件的情况发生。当然程序设计时,也可以在第3行直接配置文件案的绝对路径,如下所示:

 D:\Python\ch14\ch14_15.txt

如果这样,就不必担心数据文件ch14_15.txt与程序文件ch14_15.py是否在相同目录了。

14-2-2 with关键词

其实Python提供一个关键词with应用在打开文件与建立文件对象时,使用方式如下:

  with open(欲打开的文件) as 文件对象:
          相关系列指令

使用这种方式打开文件,最大特色是可以不必在程序中关闭文件,with指令会在结束不需要此文件时自动将它关闭,文件经“with open( ) as文件对象”打开后会有一个文件对象,就可以使用前一节的read( )读取此文件对象的内容。

程序实例ch14_16.py:使用with关键词重新设计ch14_15.py。

# ch14_16.py

fn = 'ch14_15.txt'          # 设定欲开启的档案
with open(fn) as file_Obj:  # 用默认mode=r开启档案,传回调案对象file_Obj
    data = file_Obj.read()  # 读取档案到变量data
    print(data)             # 输出变量data相当于输出档案

执行结果 与ch14_15.py相同。

由于整个文件是以字符串方式被读取与储存,所以打印字符串时最后一行的空白行也将显示出来,不过我们可以使用rstrip( )将data字符串变量(文件)末端的空格符删除。

程序实例ch14_17.py:重新设计ch14_16.py,但是删除文件末端的空白。

# ch14_17.py

fn = 'ch14_15.txt'          # 设定欲开启的档案
with open(fn) as file_Obj:  # 用默认mode=r开启档案,传回调案对象file_Obj
    data = file_Obj.read()  # 读取档案到变量data
    print(data.rstrip())    # 输出变量data相当于输出档案,同时删除末端字符

执行结果

深石数位
深度学习滴水穿石
Deep Learning

由执行结果可以看到文件末端不再有空白行了。

14-2-3 逐行读取文件内容

在Python若想逐行读取文件内容,可以使用下列循环:

 for line infile_Obj:  # line和 fileObj可以自行取名, file_Obj是文件对象
     循环相关系列指令

程序实例ch14_18.py:逐行读取和输出文件。

# ch14_18.py

fn = 'ch14_15.txt'          # 设定欲开启的档案
with open(fn) as file_Obj:  # 用默认mode=r开启档案,传回调案对象file_Obj
    for line in file_Obj:   # 逐行读取档案到变量line
        print(line)         # 输出变量line相当于输出一行

执行结果

深石数位

深度学习滴水穿石

Deep Learning

因为以记事本编辑的ch14_15.txt文本文件每行末端有换行符号,同时print( )在输出时也有一个换行输出的符号,所以才会得到上述每行输出后有空一行的结果。

程序实例ch14_19.py:重新设计ch14_18.py,但是删除每行末端的换行符号。

# ch14_19.py

fn = 'ch14_15.txt'           # 设定欲开启的档案
with open(fn) as file_Obj:   # 用默认mode=r开启档案,传回调案对象file_Obj
    for line in file_Obj:    # 逐行读取档案到变量line
        print(line.rstrip()) # 输出变量line相当于输出一行,同时删除末端字符

执行结果

深石数位
深度学习滴水穿石
Deep Learning

14-2-4 逐行读取使用readlines( )

使用with关键词配合open( )时,所打开的文件对象当前只在with区块内使用,特别是想要遍历此文件对象时。Python另外有一个方法readlines( )可以逐行读取,同时以列表方式储存,另一个特色是读取时每行的换行字符皆会储存在列表内。当然更重要的是我们可以在with区块外遍历原先文件对象内容。
在这里插入图片描述

在ch14文件夹有下列ch14_20.txt文件。

程序实例ch14_20.py:使用readlines( )逐行读取ch14_20.txt,存入列表,然后打印此列表的结果。

# ch14_20.py

fn = 'ch14_20.txt'          # 设定欲开启的档案
with open(fn) as file_Obj:  # 用默认mode=r开启档案,传回调案对象file_Obj
    obj_list = file_Obj.readlines()  # 每次读一行

print(obj_list)             # 打印列表

执行结果

['明志工专\n', '台北工专\n', '我爱明志工专\n']

由上述执行结果可以看到在txt文件的换行字符也出现在列表元素内。

程序实例ch14_21.py:逐行输出ch14_20.py所保存的列表内容。

# ch14_21.py

fn = 'ch14_20.txt'          # 设定欲开启的档案
with open(fn) as file_Obj:  # 用默认mode=r开启档案,传回调案对象file_Obj
    obj_list = file_Obj.readlines()  # 每次读一行

for line in obj_list:
    print(line.rstrip())    # 打印列表

执行结果

明志工专
台北工专
我爱明志工专

14-2-5 数据组合

Python的多功能用途,可以让我们很轻松地组合数据,例如,我们可以将原先分成3行显示的数据,以隔一个空格方式显示。

程序实例ch14_22.py:重新设计ch14_21.py,将分成3行显示的数据用1行显示。

# ch14_22.py

fn = 'ch14_20.txt'          # 设定欲开启的档案
with open(fn) as file_Obj:  # 用默认mode=r开启档案,传回调案对象file_Obj
    obj_list = file_Obj.readlines()  # 每次读一行

str_Obj = ''                # 先设为空字符串
for line in obj_list:       # 将各行字符串存入
    str_Obj += line.rstrip()

print(str_Obj)              # 打印文件字符串

执行结果

明志工专台北工专我爱明志工专

14-2-6 字符串的替换

使用Word处理时常常会使用寻找/取代功能,Python也有这个方法可以使新字符串取代旧字符串。

字符串对象.replace(旧字符串, 新字符串) # 在字符串对象内,新字符串将取代旧字符串

程序实例ch14_23.py:重新设计ch14_21.py,但是将“工专”改为“科大”。

# ch14_23.py

fn = 'ch14_20.txt'              # 设定欲开启的档案
with open(fn) as file_Obj:      # 传回调案物件file_Obj
    data = file_Obj.read()      # 读取档案到变量data
    new_data = data.replace('工专', '科大') # 新变量储存
    print(new_data.rstrip())    # 输出档案

执行结果

明志科大
台北科大
我爱明志科大

14-2-7 数据的搜寻

使用Word软件时也常会有寻找功能,使用Python这类工作变得相对简单。在ch14文件夹找到ch14_20.txt文件。

程序实例ch14_24.py:数据搜寻的应用,这个程序会读取sse.txt文件,然后要求输入欲搜寻的字符串,最后会响应此字符串是否在sse.txt文件中。
在这里插入图片描述

# ch14_24.py

fn = 'sse.txt'              # 设定欲开启的档案
with open(fn) as file_Obj:  # 用默认mode=r开启档案,传回调案对象file_Obj
    obj_list = file_Obj.readlines()  # 每次读一行

str_Obj = ''                # 先设为空字符串
for line in obj_list:       # 将各行字符串存入
    str_Obj += line.rstrip()

findstr = input("请输入欲搜寻字符串 = ")
if findstr in str_Obj:      # 搜寻档案是否有欲寻找字符串
    print("搜寻 %s 字符串存在 %s 档案中" % (findstr, fn))
else:
    print("搜寻 %s 字符串不存在 %s 档案中" % (findstr, fn))

执行结果

请输入欲搜寻字符串 = Stone
搜寻 Stone 字符串存在 sse.txt 档案中

14-2-8 数据搜寻使用find( )

对于字符串的使用,Python提供一个方法find( ),这个方法除了可以执行数据搜寻以外,如果搜寻到数据还会传回数据的索引位置,如果没有找到则传回-1。

   index = S.find(sub[, start[, end]]) # S代表被搜寻的字符串,sub是欲搜寻字符串

index是如果搜寻到时传回的索引值,start和end代表可以被搜寻字符串的区间,若是省略表示全部搜寻,如果没有找到则传回-1给index。

程序实例ch14_25.py:重新设计ch14_24.py,当搜寻到字符串时同时列出字符串所在索引的位置。

# ch14_25.py

fn = 'sse.txt'              # 设定欲开启的档案
with open(fn) as file_Obj:  # 用默认mode=r开启档案,传回调案对象file_Obj
    obj_list = file_Obj.readlines()  # 每次读一行

str_Obj = ''                # 先设为空字符串
for line in obj_list:       # 将各行字符串存入
    str_Obj += line.rstrip()

findstr = input("请输入欲搜寻字符串 = ")
index = str_Obj.find(findstr)     # 搜寻findstr字符串是否存在
if  index >= 0:             # 搜寻档案是否有欲寻找字符串
    print("搜寻 %s 字符串存在 %s 档案中" % (findstr, fn))
    print("在索引 %s 位置出现" % index)
else:
    print("搜寻 %s 字符串不存在 %s 档案中" % (findstr, fn))

执行结果
在这里插入图片描述

14-3 写入文件

程序设计时一定会碰上要求将执行结果保存起来的情况,此时就可以将执行结果存入文件内。

14-3-1 将执行结果写入空的文件内

打开文件open( )函数使用时默认是mode=‘r’读取文件模式,因此如果打开文件是供读取可以省略mode=‘r’。若是要供写入,那么就要设定写入模式mode=‘w’,程序设计时可以省略mode,直接在open( )函数内输入‘w’。如果所打开的文件需要读取和写入可以使用‘r+’。如果所打开的文件不存在open( )会建立该文件对象,如果所打开的文件已经存在,原文件内容将被清空。

至于输出到文件可以使用write( )方法,语法格式如下:

程序实例ch14_26.py:输出数据到文件的应用。

文件对象.write(欲输出数据)  # 可将数据输出到文件对象
# ch14_26.py
fn = 'out14_26.txt'
string = 'I love Python.'

with open(fn, 'w') as file_Obj:
    file_Obj.write(string)

执行结果 这个程序执行时在Python Shell窗口看不到结果,必须至ch14工作目录查看所建的out14_26.txt文件,同时打开可以得到下列结果。
在这里插入图片描述

14-3-2 写入数值资料

write( )输出时无法输出数值数据,可参考下列错误范例。

程序实例ch14_27.py:使用write( )输出数值数据产生错误的实例。

# ch14_27.py
fn = 'out14_27.txt'
x = 100

with open(fn, 'w') as file_Obj:
    file_Obj.write(x)               # 直接输出数值x产生错误

执行结果

Traceback (most recent call last):
  File "e:\桌面Desktop\Python王者归来\代码\ch14\ch14_27.py", line 6, in <module>
    file_Obj.write(x)               # 直接输出数值x产生错误
    ^^^^^^^^^^^^^^^^^
TypeError: write() argument must be str, not int

如果想要使用write( )将数值数据输出,必须使用str( )将数值数据转成字符串数据。

# ch14_28.py
fn = 'out14_28.txt'
x = 100

with open(fn, 'w') as file_Obj:
    file_Obj.write(str(x))      # 使用str(x)输出

程序实例ch14_28.py:将数值数据转成字符串数据输出的实例。这个程序执行时在Python Shell窗口看不到结果,必须至ch14工作目录查看所建的out14_28.txt文件,同时打开可以得到下列结果。

执行结果
在这里插入图片描述

14-3-3 输出多行数据的实例

如果多行数据输出到文件,设计程序时需留意各行间的换行符号问题,write( )不会主动在行的末端加上换行符号,如果有需要需自己处理。

程序实例ch14_29.py:使用write( )输出多行数据的实例。

# ch14_29.py
fn = 'out14_29.txt'
str1 = 'I love Python.'
str2 = 'Learn Python from the best book.'

with open(fn, 'w') as file_Obj:
    file_Obj.write(str1)
    file_Obj.write(str2)

执行结果 这个程序执行时在Python Shell窗口看不到结果,必须至ch14工作目录查看所建的out14_29.txt文件,同时打开可以得到下列结果。
在这里插入图片描述

其实输出至文件时我们可以使用空格或换行符号,以便获得想要的输出结果。

程序实例ch14_30.py:增加换行符号方式重新设计ch14_30.py。

# ch14_30.py
fn = 'out14_30.txt'
str1 = 'I love Python.'
str2 = 'Learn Python from the best book.'

with open(fn, 'w') as file_Obj:
    file_Obj.write(str1 + '\n')
    file_Obj.write(str2 + '\n')

执行结果 这个程序执行时在Python Shell窗口看不到结果,必须至ch14工作目录查看所建的out14_30.txt文件,同时打开可以得到下列结果。
在这里插入图片描述

14-3-4 建立附加文件

建立附加文件主要是可以将文件输出到所打开的文件末端,当以open( )打开时,需增加参数mode=‘a’或是用‘a’,其实a是append的缩写。用open( )打开文件使用‘a’参数时,如果所打开的文件不存在,Python会打开文件供写入;如果所打开的文件存在,Python在执行写入时不会清空原先的文件内容。

程序实例ch14_31.py:建立附加文件的应用。

# ch14_31.py
fn = 'out14_31.txt'
str1 = 'I love Python.'
str2 = 'Learn Python from the best book.'

with open(fn, 'a') as file_Obj:
    file_Obj.write(str1 + '\n')
    file_Obj.write(str2 + '\n')

执行结果 本书ch14工作目录没有out14_31.txt文件,所以执行第一次时,可以建立out14_31.txt文件,然后得到下列结果。
在这里插入图片描述

执行第二次时可以得到下列结果。

在这里插入图片描述

上述只要持续执行,输出数据将持续累积。

14-4 shutil模块

这个模块有提供一些方法可以让我们在Python程序内执行文件或目录的复制、删除、更改位置和更改名称。当然在使用前须加上下列加载模块指令。

 import  shutil  # 加载模块指令

14-4-1 文件的复制copy( )

在shutil模块可以使用copy( )执行文件的复制,语法格式如下:

   shutil.copy(source, destination)

上述可将source文件复制到destination目的位置,执行前source文件一定要存在否则会产生错误。

程序实例ch14_32.py:执行文件复制的应用。

# ch14_32.py
import shutil

shutil.copy('source.txt', 'dest.txt')       # 目前工作目录档案复制
shutil.copy('source.txt', 'D:\\Python')     # 目前工作目录档案复制至D:\Python
shutil.copy('D:\\Python\\source.txt', 'D:\\dest.txt') # 不同工作目录档案复制

执行结果 这个程序没有列出任何数据,它的说明如下:

第4行,当前工作目录source.txt复制一份在当前工作目录,文件名是dest.txt。

第5行,当前工作目录source.txt使用相同名称复制一份在D:\Python。

第6行,D:\Python目录source.txt复制一份在D:\,名称是dest.txt。

14-4-2 目录的复制copytree( )

copytree( )的语法格式与copy( )相同,只不过这是复制目录,复制时目录底下的子目录或文件也将被复制,此外,执行前目录一定要存在否则会产生错误。

程序实例ch14_33.py:目录复制的应用。

# ch14_33.py
import shutil

shutil.copytree('old14', 'new14')                   # 目前工作目录的目录复制
shutil.copytree('D:\\Python\\old14', 'D:\\new14')   # 不同工作目录的目录复制

执行结果 这个程序没有列出任何数据,它的说明如下:

第4行,当前工作目录old14复制一份在当前工作目录,名称是new14。

第5行,D:\Python复制old14目录至D:\,名称是new14。

14-4-3 文件的移动move( )

在shutil模块可以使用move( )执行文件的移动,语法格式如下:

shutil.move(source, destination)

上述可将source文件移动到destination目的位置,执行前source文件一定要存在否则会产生错误,执行后source文件将不再存在。

程序实例ch14_34.py:将当前目录的data34.txt移至当前目录的test34子目录。

# ch14_34.py
import shutil

shutil.move('data34.txt', '.\\test34')  # 移动目前工作目录data34.txt

执行结果 执行前当前目录底下需有test34子目录,然后可以得到下列结果。
在这里插入图片描述

14-4-4 文件名的更改move( )

在移动过程如果destination路径含有文件名,则可以达到更改名称的效果。

程序实例ch14_35.py:在同目录底下更改文件名。上述程序会将data35.txt改名为out35.txt。

# ch14_35.py
import shutil

shutil.move('data35.txt', 'out35.txt')  # 更改文件名

在文件移动过程中若是destination的目录不存在,也将造成文件名的更改。

程序实例ch14_36.py:文件名更改的另一种状况。

# ch14_36.py
import shutil

shutil.move('data36.txt', 'D:\\Python\\out36')  # out36不存在

执行结果

执行结果 下列是验证结果。
在这里插入图片描述

上述执行前D:\Python\out36不存在,将以D:\Python\out36.txt存储此文件。

14-4-5 目录的移动move( )

这个move( )也可以执行目录的移动,在移动时子目录也将随着移动。

程序实例ch14_37.py:将当前工作目录的子目录dir37移至D:\Python目录下。

# ch14_37.py
import shutil

shutil.move('dir37', 'D:\\Python')  

执行结果 下列是验证结果。
在这里插入图片描述

14-4-6 目录的更改名称move( )

如果在移动过程destination的目录不存在,此时就可以达到目录更改名称的目的了,甚至路径名称也可能更改。

程序实例ch14_38.py:将当前子目录dir38移动至D:\Python同时改名为out38。

# ch14_38.py
import shutil

shutil.move('dir38', 'D:\\Python\\out38')  

执行结果
在这里插入图片描述

14-4-7 删除底下有数据的目录rmtree( )

os模块的rmdir( )只能删除空的目录,如果要删除含数据文件的目录须使用本节所述的rmtree( )。

程序实例ch14_39.py:删除dir39目录,这个目录底下有数据文件data39.txt。执行后下列D:\Python\ch14\dir39将被删除。

# ch14_39.py
import shutil

shutil.rmtree('dir39')

执行结果
在这里插入图片描述

14-4-8 安全删除文件或目录send2trash( )

Python内置的shutil模块在删除文件后就无法复原了,当前有一个第三方的模块send2trash,执行删除文件或文件夹后是将被删除的文件放在回收站,如果后悔可以救回。不过在使用此模块前须先下载这个外部模块。可以进入安装Python的文件夹,然后在DOS环境安装此模块,安装指令如下:

  pip install send2trash

有关安装第3方模块的方法可参考附录B。安装完成后就可以使用下列方式删除文件或目录了。

  import      send2trash               # 导入send2trash模块
  send2trash.send2trash(文件或文件夹)  # 语法格式

程序实例ch14_40.py:删除文件data40.txt,未来可以在回收站找到此文件。

# ch14_40.py
import send2trash

send2trash.send2trash('data40.txt') 

执行结果 通过回收站可以找到data40.txt。

14-5 文件压缩与解压缩zipFile

Windows操作系统有提供功能将一般文件或目录压缩,压缩后的扩展名是zip,Python内有zipFile模块也可以将文件或目录压缩以及解压缩。当然程序开头需要加上下列指令导入此模块。

 import  zipFile

14-5-1 执行文件或目录的压缩

执行文件压缩前首先要使用ZipFile( )方法建立一份压缩后的档名,在这个方法中另外要加上‘w’参数,注明未来是供write( )方法写入。

fileZip = zipfile.ZipFile(‘out.zip', ‘w')  # out.zip是未来储存压缩结果

上述fileZip和out.zip皆可以自由设定名称,fileZip是压缩文件对象代表的是out.zip,未来将被压缩的文件数据写入此对象,就可以将结果存入out.zip。虽然ZipFile( )无法执行整个目录的压缩,不过可用循环方式将目录底下的文件压缩,即可达到压缩整个目录的目的。

程序实例ch14_41.py:这个程序会将当前工作目录底下的zipdir41目录压缩,压缩结果储存在out41.zip内。这个程序执行前的zipdir41内容如下:
在这里插入图片描述

下列是程序内容。

# ch14_41.py
import zipfile
import glob, os

fileZip = zipfile.ZipFile('out41.zip', 'w')
for name in glob.glob('zipdir41/*'):        # 遍历zipdir41目录
    fileZip.write(name, os.path.basename(name), zipfile.ZIP_DEFLATED)
    
fileZip.close()

执行结果 可以在相同目录得到下列压缩文件out41。

在这里插入图片描述

14-5-2 读取zip文件

ZipFile对象有namelist( )方法可以传回zip文件内所有被压缩的文件或目录名称,同时以列表方式传回此对象。这个传回的对象可以使用infolist( )方法传回各元素的属性,如文件名filename、文件大小file_size、压缩结果大小compress_size、文件时间data_time。

程序实例ch14_42.py:将ch14_41.py所建的zip文件解析,列出所有被压缩的文件,以及文件名、文件大小和压缩结果大小。

# ch14_42.py
import zipfile

listZipInfo = zipfile.ZipFile('out41.zip', 'r')
print(listZipInfo.namelist())       # 以列表列出所有压缩文件案
print("\n")
for info in listZipInfo.infolist():
    print(info.filename, info.file_size, info.compress_size)

执行结果

['20161024.jpg', 'antarctica2.jpg', 'forZipTest.docx', 'IMG_1658.jpg', 'IMG_8036.jpg', 'IMG_8096.jpg', 'IMG_8957.JPG']


20161024.jpg 166763 166531
antarctica2.jpg 1440258 1430105
forZipTest.docx 1266045 1252488
IMG_1658.jpg 1478242 1475740
IMG_8036.jpg 2885322 2877251
IMG_8096.jpg 1473764 1471145
IMG_8957.JPG 129424 126337

14-5-3 解压缩zip文件

解压缩zip文件可以使用extractall( )方法。

程序实例ch14_43.py:将程序实例ch14_41.py所建的out41.zip解压缩,同时将解压缩结果存入out43目录。

# ch14_43.py
import zipfile

fileUnZip = zipfile.ZipFile('out41.zip')
fileUnZip.extractall('out43')
fileUnZip.close()

执行结果

在这里插入图片描述

14-6 认识编码格式encode

当前为止所谈到的文本文件(.txt)的文件打开有关文件编码部分皆是使用Windows操作系统默认方式,文本模式下常用的编码方式有utf-8和cp950。使用open( )打开文件时,可以增加另一个常用的参数encoding,整个open( )的语法将如下所示:

  file_Obj = open(file, mode="r", encoding="utf-8")

14-6-1 中文Windows操作系统记事本默认的编码

请打开中文Windows操作系统的记事本建立下列文件。

请执行“文件/另存为”命令。

上述默认编码是ANSI,在这个编码格式下,在Python的open( )内我们可以使用预设的encoding=“cp950”编码,因为这是Python预设所以我们可以省略此参数。请将上述文件使用默认的ANSI编码存至ansi14_44.txt。
在这里插入图片描述

程序实例ch14_44.py:使用encoding=“950”打开ansi14_44.txt,然后输出。

# ch14_44.py

fn = 'ansi14_44.txt'                    # 设定欲开启的档案
file_Obj =  open(fn, encoding='cp950')  # 用预设encoding='cp950'开启档案
data = file_Obj.read()                  # 读取档案到变量data
file_Obj.close()                        # 关闭档案对象
print(data)                             # 输出变量data相当于输出档案

执行结果

Python逄晟
卼氪寥懂

14-6-2 utf-8编码

utf-8英文全名是8-bit Unicode Transformation Format,这是一种适合多语系的编码规则,主要方法是使用可变长度字节方式储存字符,以节省内存空间。例如,对于英文字母而言是使用1个字节空间储存即可,对于含有附加符号的希腊文、拉丁文或阿拉伯文等则用2个字节空间储存字符,两岸华人所使用的中文字则是以3个字节空间储存字符,只有极少数的平面辅助文字需要4个字节空间储存字符。也就是说这种编码规则已经包含了全球所有语言的字符了,所以采用这种编码方式设计网页时,其他国家的浏览器只要支持utf-8编码皆可显示。例如,美国人即使使用英文版的Internet Explorer浏览器,也可以正常显示中文字。

另外,有时我们在网络世界浏览其他国家的网页时,会发生显示乱码情况,主要原因就是对方网页设计师并没有将此属性设为“utf-8”。例如,早期最常见的是,中国大陆简体中文的编码是“gb2312”,这种编码方式是以2个字符组储存一个简体中文字,由于这种编码方式不适用多语系,无法在繁体中文Windows环境中使用,所以如果中国大陆的网页设计师采用此编码,将造成港、澳或台湾繁体中文Widnows的用户在繁体中文窗口环境浏览此网页时出现乱码。

其实utf-8是国际通用的编码,如果你使用Linux或Max OS,一般也是用国际编码,所以如果打开文件发生错误,请先检查文件的编码格式。请打开ansi14_44.txt文件,然后执行另存新文件,此时编码规则请选utf-8编码,将文件存入utf14_45.txt,如下所示:
在这里插入图片描述

程序实例ch14_45.py:重新设计ch14_44.py,使用encoding=‘950’打开文件发生错误的实例。

# ch14_45.py

fn = 'utf14_45.txt'                     # 设定欲开启的档案
file_Obj =  open(fn, encoding='cp950')  # 用预设encoding='cp950'开启档案
data = file_Obj.read()                  # 读取档案到变量data
file_Obj.close()                        # 关闭档案对象
print(data)                             # 输出变量data相当于输出档案

执行结果

Traceback (most recent call last):
  File "e:\桌面Desktop\Python王者归来\代码\ch14\ch14_45.py", line 5, in <module>
    data = file_Obj.read()                  # 读取档案到变量data
           ^^^^^^^^^^^^^^^
UnicodeDecodeError: 'cp950' codec can't decode byte 0xa8 in position 13: illegal multibyte sequence

上述很明显指出是decode错误。

程序实例ch14_46.py:重新设计ch14_45.py,使用encoding=‘utf-8’。

# ch14_46.py

fn = 'utf14_45.txt'                     # 设定欲开启的档案
file_Obj =  open(fn, encoding='utf-8')  # 用encoding='utf-8'开启档案
data = file_Obj.read()                  # 读取档案到变量data
file_Obj.close()                        # 关闭档案对象
print(data)                             # 输出变量data相当于输出档案

执行结果

Python语言
王者归来

14-6-3 认识utf-8编码的BOM

使用中文Windows操作系统的记事本以utf-8执行编码时,操作系统会在文件前端增加字节顺序记号(Byte Order Mark, BOM),俗称文件前端代码,主要功能是判断文字以Unicode表示时,字节的排序方式。

程序实例ch14_47.py:重新设计ch14_20.py,使用逐行读取方式读取utf-8编码格式的utf14_45.txt文件,验证BOM的存在。

# ch14_47.py

fn = 'utf14_45.txt'                             # 设定欲开启的档案
with open(fn, encoding='utf-8') as file_Obj:    # 开启utf-8档案
    obj_list = file_Obj.readlines()             # 每次读一行

print(obj_list)                                 # 打印串行

执行结果

['\ufeffPython语言\n', '王者归来\n']

从上述执行结果可以看到\ufeff字符,其实u代表这是Unicode编码格式,fe和ff是16进位的编码格式,这是代表编码格式。在utf-8的编码中有2种编码格式主张,有一派主张数值较大的byte要放在前面,这种方式称Big Endian(BE)系统。另一派主张数值较小的byte要放在前面,这种方式称Little Endian(LE)系统。以笔者名字的“魁”为例,Unicode的码值是0x9B41,若是使用BE系统,码值编法是0x9B 0x41。若是使用LE系统,码值编法是0x41 0x9B。当前Windows系统的编法是LE系统,它的BOM内容是\ufeff,由于当前没有所谓的\ufffe内容,所以一般就用BOM内容是\ufeff代表这是LE的编码系统。这2个字符在Unicode中不占空间,所以许多时候是感觉不到它们的存在的。

open( )函数使用时,也可以很明确地使用encoding=‘utf-8-sig’格式,这时即使是逐行读取也可以将BOM去除。

程序实例ch14_48.py:重新设计ch14_47.py,使用encoding=‘utf-8-sig’格式。

# ch14_48.py

fn = 'utf14_45.txt'                               # 设定欲开启的档案
with open(fn, encoding='utf-8-sig') as file_Obj:  # 开启utf-8档案
    obj_list = file_Obj.readlines()               # 每次读一行

print(obj_list)                                   # 打印列表

执行结果 从执行结果可以看到\ufeff字符没有了。

['Python语言\n', '王者归来\n']

程序实例ch14_49.py:重新设计ch14_47.py,这次改读取utf14_49.txt,并观察执行结果,可以看到\ufeff字符不见了。

# ch14_49.py

fn = 'utf14_49.txt'                             # 设定欲开启的档案
with open(fn, encoding='utf-8') as file_Obj:    # 开启utf-8档案
    obj_list = file_Obj.readlines()             # 每次读一行

print(obj_list)                                 # 打印列表

执行结果

['Python语言\n', '王者归来\n']

14-7 剪贴板的应用

剪贴板的功能是属第三方pyperclip模块内,使用前需使用下列方式安装此模块,更多知识可参考附录B:

 pip install pyperclip

然后程序前面加上下列导入pyperclip模块功能。

import pyperclip

安装完成后就可以使用下列两个方法:

copy( ):可将列表数据复制至剪贴板。
paste( ):将剪贴板数据复制回字符串变量。

程序实例ch14_50.py:将数据复制至剪贴板,再将剪贴板数据复制回字符串变量string,同时打印string字符串变量。

# ch14_50.py
import pyperclip

pyperclip.copy('明志科大-勤劳朴实')     # 将字符串拷贝至剪贴簿
string = pyperclip.paste()              # 从剪贴簿拷贝回string
print(string)                           # 打印

执行结果
在这里插入图片描述

其实上述执行第4行后,如果你打开剪贴板(可打开Word再进入剪贴板功能)可以看到“明志科大-勤劳朴实”字符串已经出现在剪贴板。程序第5行则是将剪贴板数据复制至string字符串变量,第6行则是打印string字符串变量。
在这里插入图片描述

在这里插入图片描述

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值