本次学习内容均来自DataWhale第26期组队学习
https://github.com/datawhalechina/team-learning-program/tree/master/OfficeAutomation
import pandas as pd
import numpy as np
1、文件自动化处理
1.1 读写文件
1.1.1 文件名和文件路径
os.path.join()是用于路径拼接的
语法:
os.path.join([path_1],[path_2],[path_3],…)
import os
os.path.join('datawale','docu')
'datawale\\docu'
os.path.join('study','datawale','docu')
'study\\datawale\\docu'
!注意:这里的双斜杠\,前面一个\表示转义。而Linux系统中,路径与文件名之间是用正斜杠’/'作分隔符的
1.1.2 当前工作目录
import os
os.getcwd()
'D:\\study\\datawhale\\OfficeAutomation'
# 改变工作路径
os.chdir("D:\\study\\datawhale\\python办公自动化")
os.getcwd()
'D:\\study\\datawhale\\python办公自动化'
1.1.3 路径操作
1.1.3.1 绝对路径和相对路径
绝对路径从根目录开始,相对路径,相对于该程序当前的工作目录
相对路径中,单个点“.” 表示当前目录;两个点“…”表示上一级目录,即父文件夹
os.path.abspath(path):表示将path相对路径转换为绝对路径,返回的是绝对路径的字符串;
os.path.isabs(paht):判断path是否是绝对路径,是则返回True,不是则返回False
# 首先看一下当前的路径,就是刚刚学习的
os.getcwd()
'D:\\study\\datawhale\\python办公自动化'
os.path.abspath(".")
'D:\\study\\datawhale\\python办公自动化'
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):返回当前路径的文件或文件夹名称
os.path.relpath("D:\\study\\datawhale\python办公自动化",'D:\\study')
'datawhale\\python办公自动化'
os.path.relpath("D:\\study\\datawhale\\python办公自动化")
'.'
os.path.relpath("D:\\study\\datawhale\\OfficeAutomation")
'..\\OfficeAutomation'
因为当前工作路径被变更为:D:\study\datawhale\python办公自动化,所以从当前路径出发到达OfficeAutomation目录,就要先到上一级datawhale目录,然后再进入OfficeAutomation目录。就到达了函数中的path
我的python办公自动化文件夹中有一张python语言的发明者吉多·范罗苏姆(Guido van Rossum) 的照片,基于这张照片,我们可以利用os.path.dirname得到这张照片的目录名
os.path.dirname("D:\\study\\datawhale\\python办公自动化\\python之父.jpg")
'D:\\study\\datawhale\\python办公自动化'
而os.path.basename则可以返回当前路径的文件或者文件夹的名字
# 返回文件名
os.path.basename("D:\\study\\datawhale\\python办公自动化\\python之父.jpg")
'python之父.jpg'
# 返回文件夹名——示例1
os.path.basename("D:\\study\\datawhale\\python办公自动化")
'python办公自动化'
# 返回文件夹名——示例2
os.path.basename("D:\\study\\datawhale")
'datawhale'
如果同时需要文件名和当前文件的目录名,则可以调用os.path.split(),获得两个字符串的元组
caFilePath = "D:\\study\\datawhale\\python办公自动化\\python之父"
os.path.split(caFilePath)
('D:\\study\\datawhale\\python办公自动化', 'python之父')
当然也可以用之前的函数分别获得路径和文件名,然后将返回的结果放在一个元组中
(os.path.dirname(caFilePath),os.path.basename(caFilePath))
('D:\\study\\datawhale\\python办公自动化', 'python之父')
结果一样
如果想获得某个路径中每个文件夹名称的字符串列表,可以利用os.path.sep和split()函数进行分割获取
os.path.sep:路径分隔符,在windows系统下返回\\,在Linux系统下返回/
os.path.sep
'\\'
caFilePath.split(os.path.sep)
['D:', 'study', 'datawhale', 'python办公自动化', 'python之父']
1.1.3.3 路径有效性检查
如果提供的路径不准确,python就会奔溃报错,os.path模块提供了一些函数,用于检查路径是否真实存在,以及判断是文件还是文件夹
os.path.exists(path):判断path参数所指的文件或者文件夹是否存在
os.path.isfile(path):判断path参数是否存在,并且是一个文件则返回True,否则返回False
os.path.isdir(path):判断path是否存在,并且是一个文件夹,则返回True,否则返回False
os.path.exists("C:\\Windows")
True
os.path.exists("D:\\study\\datawhale\python办公自动化\\hello.jpg")
False
os.path.isfile("D:\\study\\datawhale\python办公自动化\\python之父.jpg") # 路径有效且为文件
True
os.path.isfile("D:\\study\\datawhale\python办公自动化") # 路径有效,但是非文件
False
os.path.isfile("D:\\study\\datawhale\OfficeAutomation\\python之父.jpg") # 文件是文件,但是路径不对
False
os.path.isdir("D:\\study")
True
os.path.isdir("D:\\studys")
False
os.path.isdir("D:\\study\\datawhale\OfficeAutomation\\python之父.jpg")
False
1.1.4 文件及文件夹操作
1.1.4.1 用 os.makedirs 创建新的文件夹
os.makedirs("D:\\study\\datawhale\\practice")
---------------------------------------------------------------------------
FileExistsError Traceback (most recent call last)
<ipython-input-40-6dd7f90855cc> in <module>
----> 1 os.makedirs("D:\\study\\datawhale\\practice")
D:\application\Anaconda3\lib\os.py in makedirs(name, mode, exist_ok)
221 return
222 try:
--> 223 mkdir(name, mode)
224 except OSError:
225 # Cannot rely on checking for EEXIST, since the operating system
FileExistsError: [WinError 183] 当文件已存在时,无法创建该文件。: 'D:\\study\\datawhale\\practice'
os.makedirs()会检查该文件夹是否已经存在,若已经存在则不会覆盖,而是报错
如果需要创建的文件夹的上一层文件夹也不存在,则会自动创建所有必要的中间文件夹
os.makedirs("D:\\study\\datawhale\\tmp\我就看看你")
1.1.4.2 查看文件大小和文件夹内容
os.path.getsize(path):返回path参数中文件的字节数(即大小)
os.listdir(path):返回path参数下的所有文件名,以列表形式呈现
os.path.getsize("D:\\study\\datawhale\\python办公自动化\\python之父.jpg")
45605
os.listdir("D:\\study\\datawhale")
['OfficeAutomation', 'practice', 'python办公自动化']
os.listdir("D:\\study\\datawhale\\python办公自动化")
['python之父.jpg', 'python学习路径.png']
如果想获取某个文件夹下所有文件的大小之和,可以写一个简单的循环
totalSize=0
for filename in os.listdir("D:\\study\\datawhale\\python办公自动化"):
path = os.path.join("D:\\study\\datawhale\\python办公自动化",filename) # 知识回顾,os.path.join(),路径拼接
totalSize += os.path.getsize(path)
print(totalSize)
292403
1.1.5 文件的读写过程
读写文件3个步骤:
①调用open(),返回一个file对象
②调用file对象的read()或者write()方法
③调用file对象的close()方法,关闭该文件
1.1.5.1 调用open()方法打开文件
调用open()函数打开一个文件,需要先传递一个路径,绝对路径或者相对路径都可以
先在给定的路径中新建一个空白的文本文件,hello.txt,其中输入hello world!
helloFile = open("D:\\study\\datawhale\\python办公自动化\\hello.txt")
print(helloFile)
<_io.TextIOWrapper name='D:\\study\\datawhale\\python办公自动化\\hello.txt' mode='r' encoding='cp936'>
可以看到open返回的是一个对象,当你需要读取或者写入到该文档时,可以调用file对象的方法
1.1.5.2 读取文件内容
read():读取文件内容
readlines():按行读取文件中的内容,所有内容放在一个列表中,列表的每个元素表示每行内容
helloFile.read()
'hello world!'
hiFile = open("D:\\study\\datawhale\\python办公自动化\\hi.txt")
hiFile.read()
'hello world! I love python~\nI enjoy python!\nI want to learn python.'
文件中的所有内容全部显示,原文件中换行的部分则以 \n 标识。
hiFile = open("D:\\study\\datawhale\\python办公自动化\\hi.txt")
hiFile.readlines()
['hello world! I love python~\n',
'I enjoy python!\n',
'I want to learn python.']
每行内容以一个元素的形式放在列表中
1.1.5.3 写入文件
open(file, mode=‘r’, buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
Open file and return a stream. Raise OSError upon failure.
open函数的默认打开方式是’r’,表示read只读,所以如果需要向打开的文件中写入东西,则需要用’w’和’a’添加模式打开一个文件
注意,写模式下,如果原文件存在,则打开,然后写入;如果原文件不存在,则新建一个文件,再打开,写入
# 1. 打开
#baconFile = open("D:\\study\\datawhale\\python办公自动化\\hello.txt",'w')
baconFile = open("D:\\study\\datawhale\\python办公自动化\\bacon.txt",'w')
# 2. 写入
baconFile.write("I love python!")
# 3.关闭
baconFile.close() # !注意:关闭后才能完成写入,从txt文件中看到写入的内容
baconFile = open("bacon.txt")
content = baconFile.read()
baconFile.close()
print(content)
I love python!
如果再次重复上述过程,但是写入的内容变化一下,结果会如何呢?
# 1. 打开
baconFile = open("D:\\study\\datawhale\\python办公自动化\\bacon.txt",'w')
# 2. 写入
baconFile.write("hello world!")
# 3.关闭
baconFile.close()
baconFile = open("bacon.txt")
content = baconFile.read()
baconFile.close()
print(content)
hello world!
结果可知,直接再次写入的内容会覆盖原来的内容,所以如果需要再原来的基础上添加内容,需要用“a”添加模式打开该文件
# 1. 打开
baconFile = open("D:\\study\\datawhale\\python办公自动化\\bacon.txt",'a')
# 2. 写入
baconFile.write("I love python!")
# 3.关闭
baconFile.close()
baconFile = open("bacon.txt")
content = baconFile.read()
baconFile.close()
print(content)
hello world!I love python!
结果在hello world!原文的后面成功添加了I love python!,但是所有的结果都显示在一行,我需要换行显示所有的结果
# 1. 打开
baconFile = open("D:\\study\\datawhale\\python办公自动化\\bacon.txt",'w')
# 2. 写入
baconFile.write("I love python!\n")
# 3.关闭
baconFile.close()
# 添加内容
# 1. 打开
baconFile = open("D:\\study\\datawhale\\python办公自动化\\bacon.txt",'a')
# 2. 写入
baconFile.write("hello world!")
# 3.关闭
baconFile.close()
baconFile = open("bacon.txt")
content = baconFile.read()
baconFile.close()
print(content)
I love python!
hello world!
注意,write()方法不会像print()函数那样,在字符串的末尾自动添加换行字符。必须自己添加该字符。
1.1.5.4 保存变量
- 1)shelve模块
定义:将对象持久化保存的方法
用途:可以作为一个简单的数据存储方案。写程序的时候如果不想用关系数据库那种重量级的去存储数据,就可以用shelve。使用shelve模块,将python中的变量保存到二进制的shelf文件中,这样程序就可以从硬盘中回复变量中的数据。
用法:使用时,只需要使用open函数获取一个shelf对象,然后对数据进行增删改查操作,在完成工作、并且将内存存储到磁盘中,最后调用close函数变回将数据写入文件。
import shelve
# 在python办公自动化里面新建一个文件夹shelve,用于存放这么模块的内容
os.makedirs("D:\\study\\datawhale\\python办公自动化\\shelve")
# 创建一个shelve对象
shelveFile = shelve.open("D:\\study\\datawhale\\python办公自动化\\shelve\\mydata")
values = ['cat','dog','mouse']
shelveFile['animals'] = values
shelveFile.close()
运行上述代码后,在shelve文件夹中产生了3个新文件:mydata.bak、mydata.dat和mydata.dir。如果是在OS X上,只会创建一个mydata.db文件。
重新打开这些文件,取出数据。shelf值不必用读或者写的模式打开,因为打开后本身就是既能读也能写。
shelveFile = shelve.open(".\\shelve\\mydata")
shelveFile['animals']
['cat', 'dog', 'mouse']
shelveFile.close() # 每次用完后都要记得关闭shelve对象
从上面示例的程序可以看出,shelve使用起来和字典非常相像,保存数据利用了key和values,查看数据也是基于key值。值得注意的是:在shelve模块中,key值必须为字符串,而value值可以为python支持的任意数据类型。
shelveFile = shelve.open(".\\shelve\\mydata")
value_1 = [10,20,30]
shelveFile['numbers'] = value_1
values_2 = ['aa','bb','cc']
shelveFile['letters'] = values_2
print(shelveFile['numbers'])
print(shelveFile['letters'])
shelveFile.close()
[10, 20, 30]
['aa', 'bb', 'cc']
因为shelve对象中数据的存储和查看形式都类似于字典,所以也可以用循环的形式打印处所有的shelve对象所有的数据
shelveFile = shelve.open(".\\shelve\\mydata")
for k,v in shelveFile.items():
print(k,v)
animals ['cat', 'dog', 'mouse']
numbers [10, 20, 30]
letters ['aa', 'bb', 'cc']
既然shelve对象使用方法和字典相似,那使用字典的一些方法对shelve中的数据进行操作,结果会如何呢?
shelveFile = shelve.open(".\\shelve\\mydata")
shelveFile['animals']
['cat', 'dog', 'mouse']
shelveFile['animals'].append('pig')
shelveFile['animals'].pop(2) # 列表下标数字为2的元素删除
'mouse'
shelveFile['animals']
['cat', 'dog', 'mouse']
经过追加和删除元素后,并没有对shelve对象中的数据文件产生任何影响,文件中的列表元素还是原来的元素。所以上述操作增减操作只是在内存中进行了修改,修改后的数据并没有被真正写入到文件中。
那应该如何操作了呢?这时就需要回写了。
shelveFile = shelve.open(".\\shelve\\mydata",writeback=True)
shelveFile['animals'].append('pig')
shelveFile['animals'].pop(2)
'mouse'
shelveFile['animals']
['cat', 'dog', 'pig']
此时,mouse被删除,pig被添加进来了。
shelveFile.close()
此外,shelve对象也有keys和values两种方法,但是返回值不是真正的列表,需要传递给list()函数,取得列表的形式。
shelveFile = shelve.open(".\\shelve\\mydata")
shelveFile.keys()
KeysView(<shelve.DbfilenameShelf object at 0x0000023CDDCFC4F0>)
list(shelveFile.keys())
['animals', 'numbers', 'letters']
list(shelveFile.values())
[['cat', 'dog', 'pig'], [10, 20, 30], ['aa', 'bb', 'cc']]
- 2) pprint.pformat()函数保存变量
假定你有一个字典,保存在一个变量中,你希望保存这个变量和它的内容,以便将来使用。pprint.pformat()函数将提供一个字符串,你可以将它写入.py 文件。该文件将成为你自己的模块,如果你需要使用存储在其中的变量,就可以导入它
import pprint
'''
使用pprint.pformat()函数保存变量
'''
books = ['时间简史','财富*之路','把时间当作朋友']
books_str = pprint.pformat(books)
# 保存到文件中
ppfile = open(".\\pp\\book_data.py",'w',encoding='utf-8')
ppfile.write("books = " + books_str + "\n")
ppfile.close()
运行上述程序,会生成一个book_data.py的文件,它的内容就是:books = [‘时间简史’,‘财富*之路’,‘把时间当作朋友’]
就是说我们利用python程序生成了另外一个python程序
未来需要这些数据时,可以这样读取:
import pp.book_data
'''
读取pformat方式保存的数据
'''
books = book_data.books
print(books)
['时间简史', '财富*之路', '把时间当作朋友']
cats = [{"name":'Jack','pet':'cat'},{"name":'Jessi','pet':'dog'}]
cats_str = pprint.pformat(cats)
# 保存到文件
catFile = open(".\\pp\\myCats.py",'w')
catFile.write("cats = " + cats_str + "\n")
catFile.close()
我们有一个字典的列表,保存在变量 cats 中。为了让 cats 中的列表在关闭交互式环境后仍然可用,我们利用pprint.pformat(),将它返回为一个字符串cat_str。当我们有了 cats 中数据的字符串形式,就很容易将该字符串写入一个文件,我们将它命名为 myCats.py。
# 读取数据
import pp.myCats
cats = myCats.cats
print(cats)
print(cats[0])
print(cats[1]['name'])
[{'name': 'Jack', 'pet': 'cat'}, {'name': 'Jessi', 'pet': 'dog'}]
{'name': 'Jack', 'pet': 'cat'}
Jessi
创建一个.py文件(而不是利用shelve模块保存变量)的好处在于:因为它是一个文本文件,所以任意一个人都可以利用任意一个文本阅读器对其中的内容进行读写,进行读取,编辑。
但是对于大多数应用来说,利用shelve模块保存数据,是将变量保存到文件的最佳方式。因为只有基本的数据类型,譬如浮点型,整型,字符串,列表和字段等可以作为简单文本写入一个文件,而file对象就不能够编码为文本了。
【补充print和pprint的区别】
pprint.pprint()函数将列表或字典中的内容“漂亮打印”到屏幕
data = ("test", [1, 2, 3,'test', 4, 5], "This is a string!",
{'age':23, 'gender':'F'})
print(data)
pprint.pprint(data)
('test', [1, 2, 3, 'test', 4, 5], 'This is a string!', {'age': 23, 'gender': 'F'})
('test',
[1, 2, 3, 'test', 4, 5],
'This is a string!',
{'age': 23, 'gender': 'F'})
本例使用了数据结构较为复杂的较长数据,可见pprint()输出的更加规范易读。
1.2 组织文件
日常需求:
• 在一个文件夹及其所有子文件夹中,复制所有的 pdf 文件(且只复制 pdf 文件)
• 针对一个文件夹中的所有文件,删除文件名中前导的零,该文件夹中有数百个文件,名为 spam001.txt、 spam002.txt、 spam003.txt 等。
• 将几个文件夹的内容压缩到一个 ZIP 文件中(这可能是一个简单的备份系统)
1.2.1shutil模块
shutil模块中有一些函数可以实现复制,移动,改名,删除文件等操作。
1.2.1.1 复制文件和文件夹
shutil.copy(source,destination) 将路径source处的文件复制到路径 destination处的文件夹(source 和 destination 都是字符串),并返回新复制文件绝对路径字符串。
其中,destination可以是一个文件的名称,也可以是一个文件夹的名称
1) 如果是一个文件夹的名称,则是将source文件复制到destination文件中
2) 如果是一个文件的名称,则是将source文件复制并且更改名称为新的destination
具体理解见实例:
import shutil
# 文件夹
shutil.copy("D:\\study\\datawhale\\python办公自动化\\bacon.txt","D:\\study\\datawhale\\practice")
'D:\\study\\datawhale\\practice\\bacon.txt'
# 文件
shutil.copy("D:\\study\\datawhale\\python办公自动化\\bacon.txt","D:\\study\\datawhale\\practice\\bacon_new.txt")
'D:\\study\\datawhale\\practice\\bacon_new.txt'
shutil.copytree(source,destination) 将source文件夹中的所有文件和文件夹复制到路径destination处的文件夹,并返回新的文件夹的绝对路径
注意:新的文件夹为新创建的文件夹,如果已经存在会报错
shutil.copytree("D:\\study\\datawhale\\python办公自动化","D:\\study\\datawhale\\practice")
---------------------------------------------------------------------------
FileExistsError: [WinError 183] 当文件已存在时,无法创建该文件。: 'D:\\study\\datawhale\\practice'
shutil.copytree("D:\\study\\datawhale\\python办公自动化","D:\\study\\datawhale\\tmp")
'D:\\study\\datawhale\\tmp2'
1.2.1.2 文件与文件夹的移动与改名
shutil.move(source,destination): 将source路径处的文件/文件夹移动到路径destination,并返回新位置的绝对路径和字符串
1)source和destination都是文件夹:如果destination不存在,则会新建destination文件夹,将source文件夹下面所有的文件和文件夹全部移动到destination,同时source文件夹会被删除,返回destination的绝对路径,即移动+重命名
2)source和destination都是文件夹:如果destination存在,则直接将source文件夹整个直接移动到destination文件夹内,同时返回source新的绝对路径,即移动
3)source和destination都是文件:如果destination不存在,source文件会被拖拽到destination处,并且重命名为destination,即移动+重命名
4)source和destination都是文件:如果destination存在,则source会被移动到destination,且覆盖原有的destination,注意会被覆盖
# source和destination是文件夹,destination不存在
shutil.move("D:\\study\\datawhale\\practice","D:\\study\\datawhale\\docu")
'D:\\study\\datawhale\\docu'
# source和destination都是文件夹,destination存在
shutil.move("D:\\study\\datawhale\\docu","D:\\study\\datawhale\\exercise")
'D:\\study\\datawhale\\exercise\\docu'
# source和destination都是文件,destination不存在
shutil.move("D:\\study\\datawhale\\exercise\\docu\\bacon_new.txt","D:\\study\\datawhale\\exercise\\docu\\egg.txt")
'D:\\study\\datawhale\\exercise\\docu\\egg.txt'
# source和destination都是文件,destination存在
shutil.move("D:\\study\\datawhale\\exercise\\egg.txt","D:\\study\\datawhale\\exercise\\docu\\egg.txt")
'D:\\study\\datawhale\\exercise\\docu\\egg.txt'
1.2.1.3 永久删除文件和文件夹
os.unlink(path):删除path处的文件
os.rmdir(path):删除path处的文件夹,并且该文件夹为空文件夹,否则报错
os.rmtree(path):删除path的文件夹,报错里面的所有文件和文件夹
为了避免文件被错误删除,第一次运行以下程序时,建议加上print()函数帮助查看是否是想要删除的程序
import os
os.getcwd()
'D:\\study\\datawhale\\exercise\\docu'
为了便于后续删除操作,修改工作路径
os.chdir("D:\\study\\datawhale\\exercise\\docu") # 更改工作路径
os.getcwd() # 检查工作路径是否修改成功
'D:\\study\\datawhale\\exercise\\docu'
for filename in os.listdir():
if filename.endswith(".dir"):
os.unlink(filename)
print(filename)
mydata.dir
1.2.1.4 用send2trash模式安全删除
shutil.rmtree(path)的删除方式是永久删除,如果有误删除的资料就不能恢复了,使用起来比较危险,而使用第三方模块send2trash,将需要删除的文件或者文件夹发送到计算机的回收站,如果误删除了还可以通过回收站恢复。
# pip install send2trash #安装send2trash模块
import send2trash
os.getcwd()
'D:\\study\\datawhale\\exercise\\docu'
send2trash.send2trash('egg.txt')
1.2.2 遍历目录树
os.walk(path):传入一个路径,返回三个值:
p:path,当前文件夹的路径字符串
d:dir,当前文件夹中子文件夹的名称,以列表形式打印,如果当前文件夹中没有子文件夹,则打印空列表[]
f:file,当前文件夹中所有文件的名称,以列表形式打印
# 一个空文件夹
for p,d,f in os.walk("D:\\study\\datawhale\\os_walk\\os_walk_1"):
print("p:",p)
print("d:",d)
print("f:",f)
p: D:\study\datawhale\os_walk\os_walk_1
d: []
f: []
# 子文件夹和文件都是空的列表
for p,d,f in os.walk("D:\\study\\datawhale\\os_walk\\os_walk_2"):
print("p:",p)
print("d:",d)
print("f:",f)
p: D:\study\datawhale\os_walk\os_walk_2
d: []
f: ['aa.xlsx', 'bacon.txt', 'hello.txt', 'hi.txt', 'python之父.jpg', 'python学习路径.png']
# 有1个子文件,且子文件为空
for p,d,f in os.walk("D:\\study\\datawhale\\os_walk\\os_walk_3"):
print("p:",p)
print("d:",d)
print("f:",f)
p: D:\study\datawhale\os_walk\os_walk_3
d: ['pp']
f: ['aa.xlsx', 'bacon.txt', 'hello.txt', 'hi.txt', 'python之父.jpg', 'python学习路径.png']
p: D:\study\datawhale\os_walk\os_walk_3\pp
d: []
f: []
如果当前文件夹中有子文件,第一轮循环是对当前文件夹进行循环,获得p,d,f3个值,然后继续对下一个子文件夹开始遍历,获得3个值
# 有2个子文件,且其中一个子文件夹中有2个文本文件
for p,d,f in os.walk("D:\\study\\datawhale\\os_walk\\os_walk_4"):
print("p:",p)
print("d:",d)
print("f:",f)
p: D:\study\datawhale\os_walk\os_walk_4
d: ['gg', 'pp']
f: ['aa.xlsx', 'bacon.txt', 'hello.txt', 'hi.txt', 'python之父.jpg', 'python学习路径.png']
p: D:\study\datawhale\os_walk\os_walk_4\gg
d: []
f: []
p: D:\study\datawhale\os_walk\os_walk_4\pp
d: []
f: ['cat.txt', 'fish.txt']
先遍历当前文件夹,然后按照顺序遍历2个子文件夹
# 有2个子文件夹,其中一个只有2个文本文件,另外一个有一个还有一个子文件夹
for p,d,f in os.walk("D:\\study\\datawhale\\os_walk\\os_walk_5"):
print("p:",p)
print("d:",d)
print("f:",f)
p: D:\study\datawhale\os_walk\os_walk_5
d: ['gg', 'pp']
f: ['aa.xlsx', 'bacon.txt', 'hello.txt', 'hi.txt', 'python之父.jpg', 'python学习路径.png']
p: D:\study\datawhale\os_walk\os_walk_5\gg
d: ['gg_1']
f: []
p: D:\study\datawhale\os_walk\os_walk_5\gg\gg_1
d: []
f: ['mydata.html']
p: D:\study\datawhale\os_walk\os_walk_5\pp
d: []
f: ['cat.txt', 'fish.txt']
从结果可以看到,循环遍历的时候,会对其中一个子文件夹遍历到没有子文件夹,才开始遍历另一个子文件夹
1.2.3 用zipfile模块压缩文件
为了方便传输文件,通常需要将文件打包成.zip格式,利用zipfile模块,python可以创建和打开压缩zip文件
1.2.3.1 创建和添加到zip文件
zipfile.ZipFile(“filename”,‘w’):以写模式创建一个压缩文件
ZipFile对象的write(“filename”,compress_type=zipfile.ZIP_DEFLATED)方法:
1)如果向write()方法中传入一个路径,Python 就会压缩该路径所指的文件, 将它加到 ZIP 文件中。
2)如果向write()方法中传入一个字符串,代表要添加的文件名。第二个参数是“压缩类型”参数,告诉计算机用怎样的算法来压缩文件。可以总是将这个值设置为 zipfile.ZIP_DEFLATED(这指定了 deflate 压缩算法,它对各种类型的数据都很有效)。
注意:写模式会擦除zip文件中所有原有的内容,如果只是希望将文件添加到原有的zip文件中,需要向zipfile.ZipFile()传入"a"作为第二个参数,以添加模式打开ZIP文件
## 1. 创建一个新的zip文件,并向其中添加新的文件
import zipfile
newZip = zipfile.ZipFile("D:\\study\\datawhale\\zip\\new.zip","w")
newZip.write("D:\\study\\datawhale\\zip\\miki.txt",compress_type = zipfile.ZIP_DEFLATED)
newZip.close()
## 2.创建一个example.zip 的压缩文件,将animals下的所有文件进行压缩
os.getcwd()
'D:\\study\\datawhale\\OfficeAutomation'
import os
newZip = zipfile.ZipFile("D:\\study\\datawhale\\zip\\example.zip",'w')
for p,d,f in os.walk("..\\animals\\"):
for filename in f:
zipPath = os.path.join(p,filename)
newZip.write(zipPath,compress_type = zipfile.ZIP_DEFLATED)
print(zipPath)
newZip.close()
..\animals\cats\scottish fold cat.txt
..\animals\dogs\chihuahua.txt
..\animals\dogs\Taidi.txt.txt
1.2.3.2 读取zip文件
调用zipfile.ZipFile(filename)函数创建一个ZipFile对象(注意大写字母Z和F),filename是要读取zip文件的文件名
ZipFile对象中的两个常用方法:
1)namelis()方法,返回zip文件中包含的所有文件和文件夹的字符串列表。
2)getinfo()方法,返回一个关于特定文件的ZipInfo对象。
ZipInfo对象的两个属性:file_size和compress_size,分别表示原来文件大小和压缩后文件大小。
os.chdir("D:\\study\\datawhale\\OfficeAutomation")
os.getcwd()
'D:\\study\\datawhale\\OfficeAutomation'
exampleZip = zipfile.ZipFile("..\\zip\\example.zip")
exampleZip.namelist()
['../animals/cats/scottish fold cat.txt',
'../animals/dogs/chihuahua.txt',
'../animals/dogs/Taidi.txt.txt']
catInfo = exampleZip.getinfo("../animals/dogs/chihuahua.txt")
catInfo.file_size
89
catInfo.compress_size
78
print("压缩后的文件只有原文件的 %s%%大小 " %(round(catInfo.compress_size/catInfo.file_size,2)))
压缩后的文件只有原文件的 0.88%大小
1.2.3.3 从zip文件中解压缩
ZipFile 对象的 extractall()方法:从zip文件中解压缩所有文件和文件夹,放到当前工作目录中。
也可以向extractall()传递的一个文件夹名称,它将文件解压缩到那个文件夹, 而不是当前工作目录。如果传递的文件夹名称不存在,就会被创建。
ZipFile 对象的 extract()方法:从zip文件中解压单个文件。
也可以向 extract()传递第二个参数, 将文件解压缩到指定的文件夹, 而不是当前工作目录。如果第二个参数指定的文件夹不存在, Python 就会创建它。extract()的返回值是被压缩后文件的绝对路径。
- extractall()
# 解压到当前文件夹中
exampleZip = zipfile.ZipFile("..\\zip\\example.zip")
exampleZip.extractall() # 默认解压到当前os.getcwd() 的那个文件夹中,即程序所在文件夹
# 解压到指定文件夹
exampleZip = zipfile.ZipFile("..\\zip\\example.zip")
exampleZip.extractall("..\\zip")
# 解压到指定文件夹,且该文件夹不存在
exampleZip = zipfile.ZipFile("..\\zip\\example.zip")
exampleZip.extractall("..\\zip\\exampleZip")
exampleZip.close()
- extract()
exampleZip = zipfile.ZipFile("..\\zip\\example.zip")
exampleZip.extract("../animals/cats/scottish fold cat.txt","..\\zip\\folder")
'..\\zip\\folder\\animals\\cats\\scottish fold cat.txt'
exampleZip.close()
2、自动发送邮件
使用Python实现自动化邮件发送,可以让你摆脱繁琐的重复性业务,节省非常多的时间。
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为发件人的邮箱
# IMAP/SMTP: ZQGMNMKPKHLKCEDD # 我自己的邮箱,账号为zhaojj0220@163.com
pwd = 'DYEPOGLZDZYLOMRI' #pwd为邮箱的授权码'DYEPOGLZDZYLOMRI'
#也可以自己注册个邮箱,邮箱授权码'DYEPOGLZDZYLOMRI' 获取方式可参考#http://help.163.com/14/0923/22/A6S1FMJD00754KNP.html
receiver = 'zhaojj0220@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邮箱发送邮件的测试" #邮件的正文内容
mail_content = "您好,第三次尝试" #邮件的正文内容
message_text = MIMEText(mail_content,'plain','utf-8') #构造文本,参数1:正文内容,参数2:文本格式,参数3:编码方式
msg.attach(message_text) # 向MIMEMultipart对象中添加文本对象
#6 添加图片
image_data = open('..\\email\\cat.jpg','rb') # 二进制读取图片
message_image = MIMEImage(image_data.read()) # 设置读取获取的二进制数据
message_image["Content-Disposition"] = 'attachment; filename="cat.jpg"' # 设置附件信息 (自己添加)
image_data.close() # 关闭刚才打开的文件
msg.attach(message_image) # 添加图片文件到邮件信息当中去
# 7 添加附件(excel表格)
atta = MIMEText(open('..\\email\\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对象
邮件发送成功
<bound method SMTP.quit of <smtplib.SMTP_SSL object at 0x00000174D25FD1C0>>