1. 文件自动化处理
1.1 读写文件
程序运行时候,可以用变量来保存运算结果,如果希望程序运行关闭后仍然能够查看,就需要将数据结果保存到文件中,下面将介绍如何使用python在硬盘上创建、保存、读取文件
1.1.1 文件与路径
文件有两个属性:
- 路径:指明文件在极端就的位置,Windows中使用反斜杠“\”作为文件夹之间的分隔符号,OS X和Linux上,是使用正斜杠’/'作为它们的路径分隔符
- 文件名
python中使用os.path.join()
函数来创建文件名称和字符串
import os
os.path.join('Datawhale','docu')
可以看到返回的是(‘Datawhale\\docu’),有两个斜杠,这是因为有一个斜杠是用来转义的
1.1.2 当前工作目录
可以利用os.getcwd()
函数,获得当前工作路径的字符串,并可以利用os.chdir()
改变它。
##获取当前文件目录
import os
os.getcwd()
##改变当前工作目录
os.chdir('E:\\数据分析') #改变当前工作目录
os.getcwd()
1.1.3 路径操作
1.1.3.1 绝对路径和相对路径
- “绝对路径”,总是从根文件夹开始。
- “相对路径”,相对于程序的当前工作目录。
- 相对路径中,单个句点“.”表示当前目录的缩写,两个句点“…”表示父文件夹。
几个常用的绝对路径和相对路径处理函数
os.path.abspath(path)
:将相对路径转换为绝对路径,将- 返回参数的绝对路径的字符串。os.path.isabs(path)
:判断是否是绝对路径,是返回True,不是则返回False
##当前路径转化为绝对路径
os.path.abspath('.')
##判断是否为绝对路径,是的话返回True,不是的话返回False
os.path.isabs('.') #False
os.path.isabs(os.path.abspath('.'))#True
1.1.3.2 路径操作
os.path.relpath(path,start)
:返回从start路径到path的相对路径的字符串。如果没提供start,就使用当前工作目录作为开始路径。os.path.dirname(path)
: 返回当前路径的目录名称。os.path.basename(path)
:返回当前路径的文件名称。
##返回start路径到path的相对路径的字符串,如果没有提供start,就使用当前工作目录作为开始路径
os.path.relpath('E:\\数据分析\\python办公','E:\\')
#'数据分析\\python办公'
##返回当前路径的目录名称
path = 'E:\\数据分析\\python办公'
os.path.dirname(path)
#'E:\\数据分析'
##返回当前路径文件名称
os.path.basename(path)
'python办公'
如果同时需要一个路径的目录名称和基本名称,可以调用os.path.split()
,获得者两个字符串的元组。
caFilePath = 'E:\\数据分析\\python办公\\【python办公自动化】task01 文件自动化处理&邮件批量处理.ipynb'
os.path.split(caFilePath) #('E:\\数据分析\\python办公\\', '【python办公自动化】task01 文件自动化处理&邮件批量处理.ipynb')
我们也可以调用os.path.dirname()
和os.path.basename()
,将它们的返回值放在一个元组中,从而得到同样的元组。
如果我们想返回每个文件夹的字符串的列表。用os.path.split()
无法得到,我们可以用split()
字符串方法,并根据os.path.sep
中的字符串进行分割。os.path.sep
变量设置为正确的文件夹分割斜杠。
caFilePath.split(os.path.sep) #['E:', '数据分析', 'python办公', '【python办公自动化】task01 文件自动化处理&邮件批量处理.ipynb']
1.1.3.3 路径有效性检查
如果提供的路径不存在,很多Python函数就会崩溃并报错。os.path
模块提供了一些函数,用于检测给定的路径是否存在,以及判定是文件还是文件。
os.path.exists(path)
:如果path参数所指的文件或文件夹存在,则返回True,否则返回False。os.path.isfile(path)
:如果path参数存在,并且是一个文件,则返回True,否则返回False。os.path.isdir(path)
:如果path参数存在,并且是一个文件夹,则返回True,否则返回False。
##路径有效性检查
print(os.path.exists('C:\\Windows'))
print(os.path.exists('C:\\else'))
print(os.path.isfile('E:\\数据分析\\python办公\\【python办公自动化】task01 文件自动化处理&邮件批量处理.ipynb'))
print(os.path.isfile('E:\\数据分析\\python办公'))
print(os.path.isdir('E:\\数据分析\\python办公\\【python办公自动化】task01 文件自动化处理&邮件批量处理.ipynb'))
print(os.path.isdir('E:\\数据分析\\python办公'))
1.1.4 文件及文件夹操作
1.1.4.1 用os.makedirs()创建新文件夹
os.makedirs()
可以创建所有必要的中间文件夹。
os.makedirs('E:\\数据分析\\practice') #查看目录,已创建,若文件夹已存在,不会覆盖,会报错
1.1.4.2 查看文件大小和文件夹内容
os.path.getsize(path)
:返回path参数中文件的字节数。
os.listdir(path)
:返回文件名字符串的列表,包含path参数中的每个文件。
##查看文件大小
os.path.getsize('E:\\数据分析\\python办公\\【python办公自动化】task01 文件自动化处理&邮件批量处理.ipynb')
##查看文件夹内容(包含的文件)
os.listdir('E:\\数据分析\\python办公')
如果想知道目录下所有文件的总字节数,可以同时使用os.path.getsize()
和os.listdir()
totalSize = 0
for filename in os.listdir('E:\\数据分析\\python办公'):
totalSize = totalSize + os.path.getsize(os.path.join('E:\\数据分析\\python办公',filename))
print(totalSize)
1.1.6 文件读写过程
读写文件3个步骤:
-
调用
open()
函数,返回一个File对象。 -
调用File对象的
read()
或write()
方法。 -
调用File对象的
close()
方法,关闭该文件。
1.1.6.1 使用open()函数打开文件
使用open()函数打开一个文件,需要向其传递一个字符串路径,该路径可以是绝对路径也可以是相对路径,open()函数将返回一个File对象
helloFile = open('E:\\数据分析\\python办公\\hello.txt')
print(helloFile)
可以看到返回的是一个File对象
1.1.6.2 读取文件内容
-
read()
:读取文件内容。 -
readlines()
:按行读取文件中的内容,取得一个字符串列表,列表中每个字符串是文本中的一行且以\n结束。
helloContent = helloFile.read()
helloContent
sonnetFile = open('E:\\数据分析\\python办公\\hello.txt')
sonnetFile.readlines()
1.1.6.3 写入文件
需要用“写模式”‘w’
和“添加模式”'a'
打开一个文件,而不能用读模式打开文件。
- w “写模式”将覆写原有的文件,从头开始。
- a “添加模式”将在已有文件的末尾添加文本。
baconFile = open('bacon.txt','w')
baconFile.write('Hello world!\n')
baconFile.close() #注意,关闭后,才能完成写入,从txt文件中看到写入的内容。
可以看到创建了一个bacon.txt文件,并且写入的内容Hello world!
baconFile = open('bacon.txt','a')
baconFile.write('Bacon is not a vegetable.')
baconFile.close()
可以发现在文件末尾写入了
baconFile = open('bacon.txt')
content = baconFile.read()
baconFile.close()
print(content)
【注意】write()
方法不会像print()函数那样,在字符串的末尾自动添加换行字符。必须自己添加该字符。
1.1.6.3 保存变量
(1)shelve模块
用shelve
模块,可以将Python中的变量保存到二进制的shelf
文件中。这样,程序就可以从硬盘中恢复变量的数据。
import shelve
shelfFile = shelve.open('mydata')
cats = ['Zonphie','Pooka','Simon']
shelfFile['cats'] = cats
shelfFile.close()
在Windows上运行前面的代码,我们会看到当前工作目录下有3个新文件:mydata.bak
、mydata.dat
和mydata.dir
。在OS X上,只会创建一个mydata.db文件。
重新打开这些文件,取出数据。注意:shelf
值不必用读模式或写模式打开,因为打开后,既能读又能写。
shelfFile=shelve.open('mydata')
print(type(shelfFile))
shelve.DbfilenameShelf
shelfFile['cats']
shelfFile.close()
就像字典一样,shelf
值有keys()
和values()
方法,返回shelf中键和值的类似列表的值。但是这些方法返回类似列表的值,却不是真正的列表,所以应该将它们传递给list()
函数,取得列表的形式。
shelfFile=shelve.open('mydata')
print(list(shelfFile.keys()))
print(list(shelfFile.values()))
shelfFile.close()
2)、用pprint.pformat()
函数保存变量
pprint.pformat()
函数返回要打印的内容的文本字符串
假如,有一个字典,保存在一个变量中,希望保存这个变量和它的内容,以便将来使用。pprint.pformat()
函数将提供一个字符串,我们可以将它写入.py文件。这个文件可以成为我们自己的模块,如果需要使用存储其中的变量,就可以导入它。
import pprint
cats = [{'name':'Zophie','desc':'chubby'},{'name':'Pooka','desc':'fluffy'}]
pprint.pformat(cats)
fileObj = open('myCats.py','w')
fileObj.write('cats = '+pprint.pformat(cats)+'\n')
fileObj.close()
myCats中内容为cats=[{'desc': 'chubby', 'name': 'Zophie'}, {'desc': 'fluffy', 'name': 'Pooka'}]
import语句导入的模块本身就是Python脚本。如果来自pprint.pformat()
的字符串保存为一个.py文件,该文件就是一个可以导入的模块。
import myCats
print(myCats.cats)
print(myCats.cats[0])
print(myCats.cats[0]['name'])
1.2 组织文件
本节将介绍如何用程序组织硬盘上已经存在的文件。比如实现文件的复制,给文件重新命名,压缩文件等等。
1.2.1 shutil模块
shutil
(或称为shell工具)模块中包含一些函数,可以在Python程序中复制、移动、改名和删除文件。要使用shutil
的函数,首先需要import shutil
1.2.1.1 复制文件和文件夹
shutil.copy(source, destination)
:将路径source处的文件复制到路径 destination处的文件夹(source 和 destination 都是字符串),并返回新复制文件绝对路径字符串。
其中destination可以是:
-
一个文件的名称,则将source文件复制为新名称的destination
-
一个文件夹,则将source文件复制到destination中
-
若这个文件夹不存在,则将source目标文件内的内容复制到destination中,若destination文件夹不存在,则自动生成该文件。(慎用,因为会将source文件复制为一个没有扩展名的名字为destination的文件,这往往不是我们希望的)
import shutil
shutil.copy('D:\\Datawhale\\python办公自动化\\bacon.txt', 'D:\\Datawhale\\practice')
os.getcwd()
shutil.copy('D:\\Datawhale\\python办公自动化\\capitalsquiz_answers1.txt', 'D:\\Datawhale\\practice\\bacon.txt')
shutil.copy('D:\\Datawhale\\python办公自动化\\bacon.txt', 'D:\\Datawhale\\exercise')
shutil.copytree(source, destination)
:将路径source处的文件夹,包括其包含的文件夹和文件,复制到路径destination处的文件夹,并返回新复制文件夹绝对路径字符串。
注:destination处的文件夹为新创建的文件夹,如已存在,则会报错
import shutil
shutil.copytree('D:\\Datawhale\\python办公自动化','D:\\Datawhale\\practice')
1.2.1.2 文件和文件夹的移动与改名
shutil.move(source, destination)
:将路径 source 处的文件/文件夹移动到路径destination,并返回新位置的绝对路径的字符串。
-
如果source和destination是文件夹,且destination已存在,则会将source文件夹下所有内容复制到destination文件夹中。移动。
-
如果source是文件夹,destination不存在,则会将source文件夹下所有内容复制到destination文件夹中,source原文件夹名称将被替换为destination文件夹名。 移动+重命名
-
如果source和destination是文件,source处的文件将被移动到destination处的位置,并以destination处的文件名进行命名,移动+重命名。
注意:如果destination中有原来已经存在同名文件,移动后,会被覆写,所以应当特别注意。
import shutil
shutil.move('D:\\Datawhale\\practice','D:\\Datawhale\\docu')
shutil.move('D:\\Datawhale\\practice','D:\\Datawhale\\docue')
shutil.move('D:\\Datawhale\\docue\\bacon.txt','D:\\Datawhale\\docu\\egg.txt')
1.2.1.3 永久删除文件和文件夹
-
os.unlink(path)
: 删除path处的文件。 -
os.rmdir(path)
: 删除path处的文件夹。该文件夹必须为空,其中没有任何文件和文件夹。 -
shutil.rmtree(path)
:删除 path 处的文件夹,它包含的所有文件和文件夹都会被删除。
注意:使用时,需要非常小心,避免删错文件,一般在第一次运行时,注释掉这些程序,并加上print()
函数来帮助查看是否是想要删除的文件。
#建议先指定操作的文件夹,并查看
os.chdir('D:\\Datawhale\\docue')
os.getcwd()
import os
for filename in os.listdir():
if filename.endswith('.dir'):
#os.unlink(filename)
print(filename)
1.2.1.4 用send2trash模块安全地删除
shutil.rmtree(path)
会不可恢复的删除文件和文件夹,用起来会有危险。因此使用第三方的send2trash
模块,可以将文件或文件夹发送到计算机的垃圾箱或回收站,而不是永久删除。因程序缺陷而用send2trash 删除的某些你不想删除的东西,稍后可以从垃圾箱恢复。
pip install send2trash #安装send2trash模块
import send2trash
send2trash.send2trash('bacon.txt')
1.2.2 遍历目录树
os.walk(path)
:传入一个文件夹的路径,在for循环语句中使用os.walk()
函数,遍历目录树,和range()函数遍历一个范围的数字类似。不同的是,os.walk()
在循环的每次迭代中,返回三个值:
- 前文件夹称的字符串。
- 当前文件夹中子文件夹的字符串的列表。
- 当前文件夹中文件的字符串的列表。
注:当前文件夹,是指for循环当前迭代的文件夹。程序的当前工作目录,不会因为os.walk()
而改变。
按照下图目录树,创建相应的文件。
import os
for folderName, subFolders,fileNames in os.walk('D:\\animals'):
print('The current folder is ' + folderName)
for subFolder in subFolders:
print('Subfolder of ' + folderName+':'+subFolder)
for filename in fileNames:
print('File Inside ' + folderName+':'+filename)
print('')
1.2.3 用zipfile模块压缩文件
利用zipfile模块中的函数,Python程序可以创建和打开(或解压)zip文件。
1.2.3.1 创建和添加到zip文件
创建一个example.zip的zip文件,并向其中添加文件。
-
zipfile.ZipFile('filename.zip', 'w')
:以写模式创建一个压缩文件 -
ZipFile
对象的write('filename','compress_type=zipfile.ZIP_DEFLATED')
方法:如果向write()
方法中传入一个路径,Python 就会压缩该路径所指的文件, 将它加到 ZIP 文件中。 如果向write()
方法中传入一个字符串,代表要添加的文件名。第二个参数是“压缩类型”参数,告诉计算机用怎样的算法来压缩文件。可以总是将这个值设置为zipfile.ZIP_DEFLATED
(这指定了 deflate 压缩算法,它对各种类型的数据都很有效)。
注意:写模式会擦除zip文件中所有原有的内容。如果只希望将文件添加到原有的zip文件中,就要向zipfile.ZipFile()
传入’a’作为第二个参数,以添加模式打开 ZIP 文件。
## 1 创建一个new.zip压缩文件,并向其中添加文件
import zipfile
newZip = zipfile.ZipFile('new.zip','w')
newZip.write('Miki.txt',compress_type=zipfile.ZIP_DEFLATED)
newZip.close()
newZip = zipfile.ZipFile('new.zip','w')
newZip.write('D:\\animals\\dogs\\Taidi.txt',compress_type=zipfile.ZIP_DEFLATED)
newZip.close()
## 2 创建一个example.zip的压缩文件,将animals文件夹下所有文件进行压缩。
import zipfile
import os
newZip = zipfile.ZipFile('example.zip','w')
for folderName, subFolders,fileNames in os.walk('D:\\animals'):
for filename in fileNames:
newZip.write(os.path.join(folderName,filename),compress_type=zipfile.ZIP_DEFLATED)
newZip.close()
1.2.3.2 读取zip文件
调用zipfile.ZipFile(filename)
函数创建一个ZipFile
对象(注意大写字母Z和F),filename是要读取zip文件的文件名。
ZipFile
对象中的两个常用方法:
-
namelis()
方法,返回zip文件中包含的所有文件和文件夹的字符串列表。 -
getinfo()
方法,返回一个关于特定文件的ZipInfo
对象。
ZipInfo
对象的两个属性:file_size
和compress_size
,分别表示原来文件大小和压缩后文件大小。1.2.3.2 读取zip文件
import zipfile,os
exampleZip = zipfile.ZipFile('example.zip')
exampleZip.namelist()
catInfo = exampleZip.getinfo('animals/Miki.txt')
catInfo.file_size
catInfo.compress_size
print('Compressed file is %s x smaller!' %(round(catInfo.file_size/catInfo.compress_size,2)))
exampleZip.close()
1.2.3.3 从zip文件中解压缩
ZipFile
对象的 extractall()
方法:从zip文件中解压缩所有文件和文件夹,放到当前工作目录中。也可以向extractall()
传递的一个文件夹名称,它将文件解压缩到那个文件夹, 而不是当前工作目录。如果传递的文件夹名称不存在,就会被创建。
ZipFile
对象的 extract()
方法:从zip文件中解压单个文件。也可以向 extract()传递第二个参数, 将文件解压缩到指定的文件夹, 而不是当前工作目录。如果第二个参数指定的文件夹不存在, Python 就会创建它。extract()的返回值是被压缩后文件的绝对路径。
import zipfile, os
exampleZip = zipfile.ZipFile('example.zip')
exampleZip.extractall('.\zip')
exampleZip.close()
exampleZip = zipfile.ZipFile('example.zip')
exampleZip.extract('animals/Miki.txt')
exampleZip.extract('animals/Miki.txt', 'D:\\animals\\folders')
exampleZip.close()
2 自动发送电子邮件
Python有两个内置库:smtplib
和email
,能够实现邮件功能,smtplib
库负责发送邮件,email
库负责构造邮件格式和内容。
邮件发送需要遵守SMTP协议,Python内置对SMTP的支持,可以发送纯文本邮件、HTML邮件以及带附件的邮件。
#1 先导入相关的库和方法
import smtplib #导入库
from smtplib import SMTP_SSL #加密邮件内容,防止中途被截获
from email.mime.text import MIMEText #构造邮件的正文
from email.mime.image import MIMEImage #构造邮件的图片
from email.mime.multipart import MIMEMultipart #把邮件的各个部分装在一起,邮件的主体
from email.header import Header #邮件的文件头,标题,收件人
#2 设置邮箱域名、发件人邮箱、邮箱授权码、收件人邮箱
host_server = 'smtp.163.com' #sina 邮箱smtp服务器 #smtp 服务器的地址
sender_163 = 'pythonauto_emai@163.com' #sender_163为发件人的邮箱
pwd = 'DYEPOGLZDZYLOMRI' #pwd为邮箱的授权码'DYEPOGLZDZYLOMRI'
#也可以自己注册个邮箱,邮箱授权码'DYEPOGLZDZYLOMRI' 获取方式可参考#http://help.163.com/14/0923/22/A6S1FMJD00754KNP.html
receiver = '********@163.com'
#3 构建MIMEMultipart对象代表邮件本身,可以往里面添加文本、图片、附件等
msg = MIMEMultipart() #邮件主体
#4 设置邮件头部内容
mail_title = 'python办公自动化邮件' # 邮件标题
msg["Subject"] = Header(mail_title,'utf-8') #装入主体
msg["From"] = sender_163 #寄件人
msg["To"] = Header("测试邮箱",'utf-8') #标题
#5 添加正文文本
mail_content = "您好,这是使用python登录163邮箱发送邮件的测试" #邮件的正文内容
message_text = MIMEText(mail_content,'plain','utf-8') #构造文本,参数1:正文内容,参数2:文本格式,参数3:编码方式
msg.attach(message_text) # 向MIMEMultipart对象中添加文本对象
#6 添加图片
image_data = open('cat.jpg','rb') # 二进制读取图片
message_image = MIMEImage(image_data.read()) # 设置读取获取的二进制数据
image_data.close() # 关闭刚才打开的文件
msg.attach(message_image) # 添加图片文件到邮件信息当中去
# 7 添加附件(excel表格)
atta = MIMEText(open('cat.xlsx', 'rb').read(), 'base64', 'utf-8') # 构造附件
atta["Content-Disposition"] = 'attachment; filename="cat.xlsx"' # 设置附件信息
msg.attach(atta) ## 添加附件到邮件信息当中去
#8 发送邮件
smtp = SMTP_SSL(host_server) #SSL登录 创建SMTP对象
smtp.login(sender_163,pwd) ## 登录邮箱,传递参数1:邮箱地址,参数2:邮箱授权码
smtp.sendmail(sender_163,receiver,msg.as_string()) # 发送邮件,传递参数1:发件人邮箱地址,参数2:收件人邮箱地址,参数3:把邮件内容格式改为str
print("邮件发送成功")
smtp.quit # 关闭SMTP对象