文件操作与模块
文件操作是很常见的功能,我们python当然也支持,python自带文件的基本操作方法,但是借助os等模块更加方便快捷。在学习过程中,我们时不时会用到模块,这里也将详细讲解模块、常用模块、以及怎样制作、发布和安装模块。
一、文件打开与关闭
1、打开文件
在Python中打开文件使用open
函数,可以打开一个已经存在的文件,或者创建一个新文件
语法格式:
open(‘文件名称’,'打开模式’)
示例:
open('test.txt','w’)
文件打开模式:
2、写入文件
“w”模式:默认是gdk中文编码,一般指定国际编码‘utf-8’
# 打开文件
fobj=open('./test.txt','w',encoding='utf-8') # 不存在就创建一个新的文件,且w会替换原来的东西
# 读写操作
fobj.write('在苍茫的大海上')
# 保存+关闭
fobj.close()
# 打开文件
fobj=open('./test.txt','w',encoding='utf-8') # 不存在就创建一个新的文件
# 读写操作
fobj.write('在苍茫的大海上,')
fobj.write('狂风卷积着乌云。')
# 保存+关闭
fobj.close()
“wb”二进制格式写入
fobj=open('./test.txt','wb') # str-->bytes
fobj.write('在乌云和大海之间'.encode('utf-8'))
fobj.close()
“a”追加写入,不覆盖,没有还会创建
fobj=open('./test.txt','a')
fobj.write('在乌云和大海之间\n')
fobj.write('海燕像黑色的闪电\n')
fobj.close()
fobj=open('./test.txt','a')
fobj.write('在高傲的飞翔\n')
fobj.close()
“ab”二进制格式写入
fobj=open('./test.txt','ab')
fobj.write('一会翅膀碰着波浪\n'.encode('utf-8'))
fobj.close()
2、读写
读取文件 read() ,将文件的内容全部读取出来。
读取指定字符个数 read(num)传入一个数字做参数,表示读取指定字符个数
# 读数据
f=open('test.txt','r')
print('*******读取全部数据(读完就自动关闭)*********')
print(f.read()) # 全读
print('*******读取指定字符个数******')
f=open('test.txt','r')
print(f.read(5))
print('*******第二次读取将从第一次读取的位置继续读取**** ')
print(f.read())
f=open('test.txt','r')
print('*******一行一行读数据*********')
print(f.readline(2))
print(f.readline()) # 继续读完一行
f=open('test.txt','r')
print('*******一行一行读取所有数据(返回列表形式)*********')
print(f.readlines()) # 读完再读就是空
print(f.readlines(2))
f=open('test.txt','r')
print(f.readlines(9)) # 1-8都是第一行,大于8就读前两行,大于16读前三行
print(f.readlines()) # 继续读完一行
print('*****rb二进制格式读数据**')
f=open('test.txt','rb')
print(f.read())
print('*****rb二进制格式读数据,解码为默认的gbk的格式**')
f=open('test.txt','rb')
data=f.read()
print(data.decode('gbk'))
4、with上下文管理
with 语句,不管在处理文件过程中是否发生异常,都能保证 with 语句执行完毕后已经关闭打开的文件句柄。(读写完数据如果忘记关闭,会造成无法释放的错误)
with open('test.txt','a') as f:
f.write('诗兴大发')
with open('test.txt','r') as f:
print(f.read())
二、文件的自动备份
1、利用脚本完成自动备份,要求用户输入文件名称,完成自动备份
def copyfile():
# 接收用户输入的文件名
old_file = input('请输入要备份的文件名:')
file_list = old_file.split(".") # 分割文件名和后缀名['test', 'txt']
# 构造新的文件名,加上备份后缀
new_file = file_list[0] + '_备份.' + file_list[1]
old_f = open(old_file, 'r') # 打开需要备份的文件
new_f = open(new_file, 'w') # 以写的模式打开新文件,不存在则创建
content = old_f.read() # 将文件内容读取出来
new_f.write(content) # 将读取的内容写入备份文件
# 将打开的文件关闭
old_f.close()
new_f.close()
copyfile()
2、如果处理超大文件,一次将全部内容读取出来显然是不合适的,在需求1的基础上改进下代码,让它备份大文件也不会导致内存被占满。
def copyfile():
# 接收用户输入的文件名
old_file = input('请输入要备份的文件名:')
file_list = old_file.split(".") # 分割文件名和后缀名['test', 'txt']
# 构造新的文件名,加上备份后缀
new_file = file_list[0] + '_备份.' + file_list[1]
try:
# 监视要处理的文件
with open(old_file, 'r') as old_f,open(new_file, 'w') as new_f:
while True:
content = old_f.read(1024) # 将文件内容每次读取1024字符
new_f.write(content) # 将读取的内容写入备份文件
if len(content)<1024:
break
except Exception as msg:
print(msg)
# 将打开的文件关闭
old_f.close()
new_f.close()
copyfile()
三、文件定位
文件定位,指的是当前文件指针读取到的位置,光标位置。在读写文件的过程中,如果想知道当前的位置,可以使用tell()
来获取
# 以读模式打开test.txt 文件
f = open('test.txt','r')
content = f.read(3) # 读取三个字符,每一个汉字是两个字节
# 查看当前游标所在位置
print(content)
cur =f.tell()
print(cur)
content = f.read(3) # 读取三个字符
# 查看当前游标所在位置
print(content)
cur =f.tell()
print(cur)
如果在操作文件的过程,需要定位到其他位置进行操作,用seek()
。
seek(offset, from)有2个参数,offset,偏移量单位字节,负数是往回偏移,正数是往前偏移,from位置:0表示文件开头,1表示当前位置,2表示文件末尾。
# 以读模式打开test.txt 文件
f = open('test.txt','rb')
content = f.read(10) # 读取三个字符
print(content)
f = open('test.txt','rb')
content = f.read(3) # 读取三个字符
print(content)
f.seek(-2, 1) # 在当前位置往回偏移两个字节
content = f.read(3) # 读取三个字符
print(content)
f.seek(-5,2) # 定位到文章末尾,往回偏移5个字节
content = f.read(3) # 读取三个字符
print(content)
f.seek(5,0) # 定位到文章开头,向前偏移5个字节
content = f.read(3) # 读取三个字符
print(content)
# 偏移量为负数,是往回偏移,正数是往前偏移
对文件进行截取需要用到truncate函数
。
f=open('test.txt','r')
print(f.read()) # 全读
f.close()
print('********截取后数据*****')
fobjA = open('test.txt','r+') # r+读写
fobjA.truncate(5) #截取15个字符(源文件也修改为截取的15个字符)
print(fobjA.read())
fobjA.close()
四、模块介绍
定义:
在python中,一个py文件就是一个模块
作用:
可以使我们有逻辑的去组织我们的python代码
以库的形式去封装功能,非常方便的去让调用者使用
可以定义函数,类,变量,也能包含可执行的代码
不同的模块可以定义相同的变量名,但是每个模块中的变量名作用域只是在本模块中
分类:
内置模块,自定义模块,第三方模块
1、模块导入
import time
print(time.ctime())
from … import 导入模块的方法
- 一个模块可能会存在很多函数,如果只想导入其中几个函数,可以使用
from xx import xx
方式导入 - 使用from导入,如果函数名相同,后面导入的会覆盖前面导入的。
- 把模块中的所有函数一次性全部导入语法格式:
from xxx import *
from time import ctime,time
print(ctime()) # 返回当前时间
print(time()) # 返回当前时间的时间戳(1970纪元后经过的浮点秒数)。
有时候导入的模块名称很长,调用的时候很不方便,这个使用就可以用as给这个模块取别名
2、OS模块操作文件
对文件进行重命名、删除等一些操作,在python中可以利用os模块。
os模块提供一些系统级别的操作命令。
指定位置创建文件夹:
os.mkdir('H:/python_learning/3') # 只能创建一级目录
os.makedirs('H:/python_learning/4/3') # 创建多级目录
os.rmdir('H:/python_learning/4/3') # 正常删除3文件夹
os.rmdir('H:/python_learning/4') # 报错,因为4文件夹里面不是空的有3
# 若想删除非空目录,需要引入shutil模块
import shutil
shutil.rmtree('H:/python_learning/4') # 4文件夹及里面所有的东西都删除啦
获取当前目录:getcwd()
import os
print(os.getcwd())
路径拼接: os.path.join(path1[, path2[, …]]) 将多个路径组合后返回
print(os.path.join(os.getcwd(),'剑指offer','4'))
遍历目录下的文件:
# 返回列表形式,且只遍历一级目录下的文件
listrs=os.listdir('H:/')
for i in listrs:
print(i)
# 使用现代方法
with os.scandir('H:/') as entires:
for i in entires:
print(i)
打印目录下的所有文件(除文件夹外)
basePath = 'H:/'
for i in os.listdir(basePath):
if os.path.isfile(os.path.join(basePath,i)): # isdir是目录
print(i)
3、time模块
import time
print(time.time()) # 时间戳 1593337142.0395858
print(time.ctime()) # Sun Jun 28 17:39:18 2020
print(time.asctime()) # Sun Jun 28 17:39:42 2020
ret = time.gmtime()
print('%s-%s-%s'%(ret.tm_year,ret.tm_mon,ret.tm_mday)) # 2020-6-28
# 本地时间
# time.struct_time(tm_year=2020, tm_mon=6, tm_mday=28, tm_hour=18, tm_min=35,
# tm_sec=48, tm_wday=6, tm_yday=180, tm_isdst=0)
print(time.localtime())
# 格式化输出时间
print(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime()))
时间格式化符号:
%y 两位数的年份表示(00-99) %Y 四位数的年份表示(000-9999)%m 月份(01-12)
%d 月内中的一天(0-31) %H 24小时制小时数(0-23) %I 12小时制小时数(01-12)
%M 分钟数(00=59) %S 秒(00-59) %a 本地简化星期名称
%A 本地完整星期名称 %b 本地简化的月份名称 %B 本地完整的月份名称
%c 本地相应的日期表示和时间表示 %j 年内的一天(001-366)
%p 本地A.M.或P.M.的等价符 %U 一年中的星期数(00-53)星期天为星期的开始
%w 星期(0-6),星期天为星期的开始 %W 一年中的星期数(00-53)星期一为星期的开始
%x 本地相应的日期表示%X 本地相应的时间表示 %Z 当前时区的名称%% %号本身
4、datatime模块
import datetime
import time
print('当前时间')
print(datetime.datetime.now()) #返回 2020-06-28 19:22:17.886006
print(datetime.date.fromtimestamp(time.time())) #时间戳直接(1512715165.0285344)转成日期格式 2020-06-28
# 当前时间+3天
print(datetime.datetime.now() + datetime.timedelta(3)) # 2020-07-01 19:22:17.886006
# 当前时间-3天
print(datetime.datetime.now() + datetime.timedelta(-3)) # 2020-06-25 19:22:17.886006
# 当前时间+3小时
print(datetime.datetime.now() + datetime.timedelta(hours=3)) # 2020-06-28 22:17.886006
# 当前时间+30分.
print(datetime.datetime.now() + datetime.timedelta(minutes=30)) # 2020-06-28 20:25:05.187355
# 当前时间3小时30分.
print(datetime.datetime.now() + datetime.timedelta(hours=3,minutes=30))
模块的制作
(1)Python文件都可以作为一个模块,模块的名字就是文件的名字。 比如创建一个test.py文件,文件中创建一个add函数。test.py就是一个模块。
(2)调用test.py模块
import test
# from test import add # 第二种导入
# from test import * # 第三种导入
res = test.add(1,3)
# res = add(1,3)
print(res)
(3)、模块测试 一般写完模块之后都会进行测试,下面来看下这个例子 写好模块之后,在模块中写了一段测试的代码。
def add(a,b):
return a+b
# 测试
res = add(1,3)
print('测试模块,%s'% res)
在main.py 导入test模块,执行时模块中的测试代码也执行了。
(4)、为了避免这种情况使用到一个__name__
的变量。
在test.py中导入执行
def add(a,b):
return a+b
# 测试
res = add(1,3)
# print('测试模块,%s'% res)
print('模块__name__变量 = %s'%__name__)
在main.py中导入执行
import test
# from test import add # 第二种导入
# from test import * # 第三种导入
res = test.add(1,3)
# res = add(1,3)
print(res)
知道__name__变量的原理之后,就可以很好的处理测试代码了。 将测试的代码放到 if name = ‘main’:
将teste.py增加限定后,运行main.py就直接输出结果,不输出测试结果
def add(a,b):
return a+b
# 测试
# res = add(1,3)
# print('测试模块,%s'% res)
if __name__ =='__main__':
res = add(1,3)
print('模块__name__变量 = %s'%__name__)
5)、all 的作用,如果一个文件中有__all__变量,那么也就意味着这个变量中的元素,会被from xxx import *
时导入(不在all里面的变量就不会被导入,不能直接调用),对于其余两种导入模块没有影响
test.py
__all__=['add','diff']
def add(a,b):
return a+b
def diff(x,y):
return x-y
def printInfo():
return '这是我自定义模块中的方法'
# 测试
# res = add(1,3)
# print('测试模块,%s'% res)
if __name__ =='__main__':
print('模块__name__变量 = %s'%__name__)
main.py
# import test
# from test import add # 第二种导入
from test import * # 第三种导入
# res = test.add(1,3)
print(add(1,3))
print(diff(34,3))
print(printInfo()) # 报错,因为不再all里面