第十二节 python的文件操作、模块操作、os模块、time、datatime模块以及模块的制作
目录
Day12新手小白学python
前言
一、文件打开关闭
二、文件读写
三、应用:文件备份脚本
四、文件定位
五、模块介绍
六、os模块操作文件
七、time、datetime模块
八、模块的制作
总结
本文介绍了 python的文件操作、模块操作、os模块、time、datatime模块以及模块的制作
文件操作一般步骤:打开文件--->读/写文件--->保存文件--->关闭文件
打开文件:•在Python中打开文件使用open函数,可以打开一个已经存在的文件,或者创建一个新文件。语法格式:open('文件名称','打开模式’)
关闭文件:语法格式:close() 方法关闭文件,如:f.close()。打开一个文件之后,一定要关闭,否则后面无法继续操作这个文件
with 上下文管理:with 语句,不管在处理文件过程中是否发生异常,都能保证 with 语句执行完毕后已经关闭打开的文件句柄。
# with的使用 上下文管理对象
# 优点:自动释放打开关联的对象
with open('Test.txt','a') as f:
# print(f.read())
f.write('我爱python')
# 文件操作
# 打开文件 open
# 默认的编码是gbk 这个是中文编码 最好的习惯是在打开文件时给他指定一个编码类型
fobj=open('./Test.txt','w',encoding="utf-8") # 打开一个文件只用于写入,如果文件不存在,则创建新文件 ./表示当前路径 fobj 是文件对象
# 开始操作 读/写操作
# fobj.write('在苍茫的大海上') # 写入数据
fobj.write('狂风卷积着乌云') # w 模式:如果该文件已存在则会将其覆盖 此时文件中只有:狂风卷积着乌云
fobj.close() # 保存关闭文件
# 以二进制的形式去写数据
# fobj=open('Test_1.txt','wb') # wb 以二进制的形式写入 即以字节的形式写入
# fobj.write("在乌云和大海之间".encode('utf-8')) # 后面必须加上.encode('utf-8') 因为需要的不是str类型,而是byte类型
# fobj.close()
# fobj=open('Test.txt','a',encoding='utf-8') # a 用于追加
# fobj.write("在乌云和大海之间\r\n")
# fobj.write('海燕像黑色的闪电\r\n')
# fobj.close()
fobj=open('Test.txt','ab') # ab 以二进制形式追加
fobj.write("今天我很好\r\n".encode('utf-8')) # 后面必须加上.encode('utf-8') 因为需要的不是str类型,而是byte类型
fobj.write('当时的发热\r\n'.encode('utf-8'))
fobj.close()
写文件:写入文件 write() 方法,参数就是需要写入的内容。
# 写模式打开一个test.txt 文件
f = open('test.txt', 'w’)
f.write('我爱中国') # write方法写入内容
f.close() # 关闭文件
读文件:
读取文件 read() ,将文件的内容全部读取出来。
# 写模式打开一个test.txt 文件
f = open('test.txt', 'r’)
f.read() # 一次性将文件内容全部取出
f.close() # 关闭文件
读取指定字符个数 read(num)传入一个数字做参数,表示读取指定字符个数
# 读模式打开一个test.txt 文件
f = open('test.txt', 'r’)
content = f.read(2) # 读取两个字符
print(content)
content = f.read()
print(content) # 第二次读取将从第一次读取的位置继续读取
f.close() # 关闭文件
readlines() 按行读取,一次性读取所有内容,返回一个列表,每一行内容作为一个元素。
#打开文件test.txt
f = open('test.txt', 'r’)
content = f.readlines() # 一次性读取所有内容,返回一个列表,列表元素为每一行内容
print(content)
f.close() # 关闭文件
readline() 按行读取,但是一次只读取一行
#打开文件test.txt
f = open('test.txt', 'r’)
content = f.readline() # 按行读取,一次读取一行
print(content)
f.close() # 关闭文件
# 读数据操作
# f=open('Test.txt','rb')
# data=f.read()
# print(data.decode('gbk')) # decode 解码 默认写进去的编码是gbk
# print(f.read()) # 一次性将文件内容全部取出
# print(f.read(10)) # 读取两个字符
# print(f.read()) # 第二次读取将从第一次读取的位置继续读取
# print(f.readline()) # 读一行数据
# print(f.readlines()) # readlines() 按行读取,一次性读取所有内容,返回一个列表,每一行内容作为一个元素。
# print(f.readlines(2)) # 指定读取的字符长度 假如指定长度小于第一行,则返回第一行全部内容
# f.close() # 关闭文件对象
# with的使用 上下文管理对象
# 优点:自动释放打开关联的对象
with open('Test.txt','a') as f:
# print(f.read())
f.write('我爱python')
# 小结
# 文件读写的几种操作方式
# read r r+ rb rb+
# r r+ 只读 适用普通的读取场景
# rb rb+ 适用于文件 图片 视频 音频这类文件的读取
# write w w+ wb+ wb a ab
# w wb w+ 每次都会创建文件
# 二进制读写的时候要注意编码问题 默认情况下 我们写入文件的编码是gbk
# a ab a+ 在原有的文件基础上[文件指针的末尾]去追加 并不会每次都创建新文件
利用脚本完成自动备份,要求用户输入文件名称,完成自动备份:
# 文件备份
def copyFile():
# 接收用户输入的文件名
old_file=input("请输入要备份的文件名:")
file_list=old_file.split('.') # 分割获取到文件的名字和文件的后缀名,以便于构建新的文件名
# 构造新的文件名.加上备份的后缀
new_file=file_list[0]+'_备份.'+file_list[1]
old_f=open(old_file,'r') # 打开需要备份的文件
new_f=open(new_file,'w',encoding='utf-8') # 以写的模式去打开新文件 若不存在则创建
content=old_f.read() # 将文件内容读取出来
new_f.write(content) # 将内容写入备份文件
old_f.close()
new_f.close()
pass
copyFile()
大文件备份:如果处理超大文件,一次将全部内容读取出来显然是不合适的,在需求1的基础上改进下代码,让它备份大文件也不会导致内存被占满。
# 读取大文件
def copyBigFile():
# 接收用户输入的文件名
old_file=input("请输入要备份的文件名:")
file_list=old_file.split('.') # 分割获取到文件的名字和文件的后缀名,以便于构建新的文件名
# 构造新的文件名.加上备份的后缀
new_file=file_list[0]+'_备份.'+file_list[1]
try:
# 监视要处理的逻辑以防出错
with open(old_file,'r') as old_f,open(new_file) as new_f:
while True:
content=old_f.read(1024) # 一次性读取1024个字符
new_f.write(content)
if len(content)<1024: # 如果文件小于1024则说明读完了 退出
break
except Exception as msg:
return msg
pass
文件定位,指的是当前文件指针读取到的位置,光标位置。在读写文件的过程中,如果想知道当前的位置,可以使用tell()来获取
# tell 返回指针当前所在的位置
with open('Test.txt','r') as f:
print(f.read(3)) # 读取三个字符
# 查看当前游标所在位置
print(f.tell()) # 说明中文汉字是占两个字符的 英文只占一个字符
print(f.read(2))
# 查看当前游标所在位置
print(f.tell()) # 说明中文汉字是占两个字符的 英文只占一个字符
pass
truncate ()可以对源文件进行截取操作
# truncate 可以对源文件进行截取操作
fobjB=open("Test.txt",'r')
print(fobjB.read())
fobjB.close()
print('截取之后的数据--------')
fobjA=open("Test.txt",'r+') # 对文件读写
fobjA.truncate(4) # 保留前4个字符
print(fobjA.read()) # 由于按字节进行截取,要注意编码格式,如:gbk中文占2个字节,而utf-8中文字符占3个字节,当文件是utf-8编码格式,但size不是3的整数倍就会解码出错
fobjA.close()
seek():如果在操作文件的过程,需要定位到其他位置进行操作,用seek()。
seek(offset, from)有2个参数,offset,偏移量单位字节,负数是往回偏移,正数是往前偏移,from位置:0表示文件开头,1表示当前位置,2表示文件末尾
# seek 控制光标所在的位置
with open('Test_1.txt','rb') as f:
data=f.read(3)
print(data.decode(encoding='utf-8')) #
f.seek(-1,1) # 因为1为当前位置 一个中文汉字又占两个字符 相当于光标又设置到了开头
data1=f.read(6)
print(data1.decode('utf-8','ignore'))
f.seek(-12,2) # 光标从末尾开始往左移6个字符 为新的光标 下次读取从新的光标开始读取 读取时是从左往右读取的
print(f.read(6).decode('utf-8','ignore'))
# 对于用'r'这种模式打开文件,在文本文件中,没有使用二进制的选项打开文件,只允许从文件的开头计算相对位置,从文件尾部位置计算或者当前位置计算就会引发异常
Python有强大的第三方库,有很多常用功能Python提供自带的内置模块。 简单的讲模块就是封装了一堆函数的py文件,就像是一个工具包,要使用里面的工具,得先将工具包那过来。模块也是一样,在程序中需要用到模块得先将模块导入。
(1)import 需要导入模块
在Python中导入模块使用import 关键字。比如我们导入一个时间模块time,获取当前时间。 模块导入一般放在文件最前面。
调用模块的方法,格式:模块名.函数名,这样调用可以防止不同模块中有同名方法导致错误。
搜索路径:
当解释器遇到import关键字,如果模块在当前的搜索路径就会被导入。 查看import导入的搜索路径,导入模块时会优先搜索当前目录下是否有这个名字的模块,所以在模块命名的时候不要与系统中的模块有重名。搜索顺序为:(1)当前目录‘(2)如果当前目录没有,到环境变量中搜索,可以用sys模块中的path变量查看所有路径;(3)如果都找不到,搜索默认路径,即python的安装路径,第三方模块安装位置,在python安装目录下的lib/site-packages/目录下。
import time # 导入time模块的全部方法
print(time.ctime()) # 调用模块中的函数 此时调用时需要模块.方法名
# import 在首次导入模块的时候会发生如下3个操作
# 1,会打开模块文件
# 2,会执行模块对应文件,将执行过程中产生的名字都丢到模块的名称空间
# 3,在程序中,会有一个模块的名称[该名称可以取别名]指向模块的名称空间去
(2)from 需要导入模块 import 需要导入的该模块的方法
一个模块可能会存在很多函数,如果只想导入其中几个函数,可以使用from xx import xx 方式导入。使用from导入,如果函数名相同,后面导入的会覆盖前面导入的。
# 另外一种导入方法 导入模块部分方法
# 只想导入time模块中的ctime,time两个方法,可以这样导入
from time import ctime,time # 部分导入
# from time import * # 导入所有方法
print(ctime()) # 部分导入直接调用导入进来的方法名即可
# from...import 首次导入发生3个步骤
# 1,以模块为准创造一个模块的名称空间
# 2,执行模块对应的文件
# 3,在当前执行文件的名称空间中拿到一个名字,该名字直接指向模块中的某一个名字,
# 意味着可以不用加任何的前缀而直接使用
# 优点:不用加前缀了代码,更加简洁
# 缺点:方法名容易与当前执行文件中名称空间中的名字冲突
# 两者相同点:都会执行模块对应的文件,并且也都会产生模块的名称空间;两者在调用功能时,都需要转到定义时寻找作用域关系
# 不同点:import需要加前缀,from...import 不需要加前缀
# 导入的模块名称很长,调用的时候很不方便,这个使用就可以用as给这个模块取别名
# import time as myTime # 加了别名 myTime指向模块的名称空间
# print(myTime.ctime())
对文件进行重命名、删除等一些操作,在python中可以利用os模块
方法 |
解释 |
os.getcwd() |
获取当前工作目录,即当前python脚本工作的目录路径 |
os.chdir("dirname") |
改变当前脚本工作目录;相当于shell下cd |
os.curdir |
返回当前目录: ('.') |
os.pardir |
获取当前目录的父目录字符串名:('..') |
os.makedirs('dir1/dir2') |
可生成多层递归目录 |
os.removedirs('dirname1') |
若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推 |
os.mkdir('dirname') |
生成单级目录;相当于shell中mkdir dirname |
os.rmdir('dirname') |
删除单级空目录,若目录不为空则无法删除,报错 |
os.listdir('dirname') |
列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印 |
os.remove() |
删除一个文件 |
os.rename("oldname","new") |
重命名文件/目录 |
os.stat('path/filename') |
获取文件/目录信息 |
os.sep |
操作系统特定的路径分隔符,win下为"\\",Linux下为"/" |
os.linesep |
当前平台使用的行终止符,win下为"\t\n",Linux下为"\n" |
os.pathsep |
用于分割文件路径的字符串 |
方法 |
解释 |
os.name |
字符串指示当前使用平台。win->'nt'; Linux->'posix' |
os.system("bash command") |
运行shell命令,直接显示 |
os.environ |
获取系统环境变量 |
os.path.abspath(path) |
返回path规范化的绝对路径 |
os.path.split(path) |
将path分割成目录和文件名二元组返回 |
os.path.dirname(path) |
返回path的目录。其实就是os.path.split(path)的第一个元素 |
os.path.basename(path) |
返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素 |
os.path.exists(path) |
如果path存在,返回True;如果path不存在,返回False |
os.path.isabs(path) |
如果path是绝对路径,返回True |
os.path.isfile(path) |
如果path是一个存在的文件,返回True。否则返回False |
os.path.isdir(path) |
如果path是一个存在的目录,则返回True。否则返回False |
os.path.join(path1[, path2[, ...]]) |
将多个路径组合后返回,第一个绝对路径之前的参数将被忽略 |
os.path.getatime(path) |
返回path所指向的文件或者目录的最后存取时间 |
os.path.getmtime(path) |
返回path所指向的文件或者目录的最后修改时间 |
import os
import shutil
# os.rename('Test.txt','Test_重命名.txt') # 重命名
# os.remove('file_del.py') # 删除文件 前提是文件必须存在
# os.mkdir('TestCJ') # 创建文件夹
# os.rmdir('TestCJ') # 删除文件夹 前提是文件存在
# os.mkdir('d:/Python编程') # 在D盘创建文件夹 只能创建一级目录 不允许多级创建
# os.mkdir('d:/Python编程/sub') # 多级创建会报错
# os.makedirs('d:/python编程/sub核心/三级目录') # 一次性创建多级目录
# os.rmdir('d:/python编程') # 只能删除空目录
# 如果要删除非空目录的话 就需要调用shutil
# shutil.rmtree('d:/python编程') # 非空文件的多级删除
# 获取当前程序的目录
# print(os.getcwd()) # 返回文件的路径 D:\PythonPro\Python.FilePro
# 路径的拼接
# print(os.path) # 返回os 所在库的的路径 D:\\rj\\python\\lib\\ntpath.py
# print(os.path.join(os.getcwd(),'venv')) # D:\PythonPro\Python.FilePro\venv
# 获取python中的目录列表 只打印一级目录
# listRS=os.listdir('d:/') # listdir老版本的用法
# for item in listRS:
# print(item)
# pass
# 使用现代版的写法 os.scandir('d:/')输出的是是个迭代器对象
# with os.scandir('d:/') as entries: # os.scandir()一般会和with使用,这样会在完成后自动释放资源
# for entry in entries:
# print(entry.name)
# pass
# pass
basePath='D:\我的信息\入党\发展对象材料\需重新打印'
for entry in os.listdir(basePath): # os.listdir(basePath)输出的是basePath路径下具体的文件名
# if os.path.isfile(os.path.join(basePath,entry)): # 看它是不是文件 os.path.isfile()括号中的是文件路径,所以需要进行拼接
# print(entry)
if os.path.isdir(os.path.join(basePath,entry)): # 看该路径下是不是有文件夹 有就返回
print(entry)
pass
time 模块的使用:
time.sleep(num) ,让程序执行暂停,num单位是秒
import time
time.sleep(5) # 程序暂停5s
time.time() #返回时间戳
# coding=gbk
import time
# print(time.time()) # 返回时间戳
# print(time.ctime()) # 返回时间戳 输出 Tue Nov 15 14:49:20 2022
# print(time.asctime()) # 输出:Tue Nov 15 14:52:19 2022
# print(time.gmtime()) # 返回utc实践的struct事件对象格式
# print(time.localtime()) # 本地时间
print(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())) # 格式化输出时间 2022-11-15 14:56:12
时间格式化符号
datetime模块:datetime模块主要用于时间计算
#返回 2022-11-15 15:00:03.902584
print(datetime.datetime.now())
#时间戳直接转成日期格式 2022-11-15
print(datetime.date.fromtimestamp(time.time()))
#当前时间+3天 输出2022-11-15 15:00:03.902584
print(datetime.datetime.now() + datetime.timedelta(3))
#当前时间-3天
print(datetime.datetime.now() + datetime.timedelta(-3))
#当前时间+3小时
print(datetime.datetime.now() + datetime.timedelta(hours=3))
#当前时间+30分.
print(datetime.datetime.now() + datetime.timedelta(minutes=30))
#当前时间1小时30分.
print(datetime.datetime.now() + datetime.timedelta(hours=3,minutes=30))
模块的定义:在python中,一个.py文件就是一个模块,模块的名字就是文件的名字
作用:可以使我们有逻辑的取组织我们的python代码;以库的形式分装功能,非常方便去让调用者使用;可以定义函数 类 变量,也包含可执行的代码。注意:不同的模块可以定义相同的变量名,但是每个模块中的变量名作用域只是在本模块中使用
模块的分类:内置模块(python自带的模块)、自定义的模块、第三方的模块(别人写的模块)
下图为定义的moudelTest模块,
# coding=gbk
# 模块的制作说明
# __all__魔术变量的作用是:如果在一个文件中存在__all__变量,那么也就意味着这个变量中的元素
# 会被from... import * 时导入,不在这个变量中的方法则不能导入,对于import方式来讲无所谓 全部都可以引用
__all__=['add','diff']
def add(x,y):
return x+y
pass
def diff(x,y):
return x-y
def printInfo():
return '这是我自定义模块中的方法'
# 测试
if __name__=="__main__": # 运行当前文件时 模块__name__变量=__main__ 但是当运行调用该模块的文件时模块__name__变量=模块名即该文件名 所以不会执行if语句的内容
res=add(2,4)
# print('测试模块,%s' %res)
print('模块__name__变量=%s' %__name__) #输出: 模块__name__变量=__main__
下图为moudelTest模块的调用,在调用模块过程中,模块名即为定义模块所在的文件名。调用该模块时会执行该模块所在的文件,该文件中的测试代码也执行了,为了避免这种情况使用到一个__name__的变量,直接运行该模块所在的文件时__name__=__main__,但是当调用模块后执行调用模块所在的文件时__name__等于模块的名字,所以可以将测试的代码放到 if __name__ = '__main__':调用该模块时便不会执行测试代码。
__all__ 的作用,如果一个文件中有__all__变量,那么也就意味着这个变量中的元素,会被from xxx import * 时导入,但不在这个变量中的方法则不能导入,对于import方式来讲无所谓,全部都可以引用
# coding=gbk
# import moudeTest # 导入模块
# from moudeTest import add # 第二种导入方式
from moudeTest import * # 第三种导入 导入全部
# res=moudeTest.add(1,3)
# print(moudeTest.diff(7,2))
# print(res) # 测试模块,6 4 原因是 调用模块时会先将该模块所在文件都执行一遍,再调用
print(add(3,5))
print(diff(7,5))
# print(printInfo()) # 会报错 对于from moudeTest import * 就不能使用了,因为没有在__all__变量中
本文介绍了 python的文件操作、模块操作、os模块、time、datatime模块以及模块的制作