本文章最初发布在 XJHui’s Blog,未经允许,任何人禁止转载!
注意:最新修改版本已发布在 这里,点击前往查看!
文件打开关闭
打开
使用open函数,可以打开已存在的文件或者创建一个新文件
-
语法格式:
open('文件名称','打开模式') # 打开模式也要使用引号
-
示例:
open('test.txt','w')
-
文件打开模式:
-
案例:使用w打开模式,打开Test.txt文件
open('./Test.txt', 'w') # 打开一个不存在的文件
运行结果:
注意:打开模式为w时,若文件不存在则会自动创建
关闭
fobj = open('./Test.txt', 'w') # open函数返回文件对象,使用fobj接受这个对象
fobj.close() # 使用:文件对象.close() 关闭打开的文件
文件的写入
将 hello world 写入test.txt 文件中
w-只写
fobj = open('./test.txt', 'w') # 使用open函数在w打开模式下打开test.txt文件
fobj.write('hello world') # 使用:文件对象.write(要写入的内容) 将字符串写入文件
fobj.close() # 写入后记得要关闭
运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/c6bc930ea474e9631c1ca9791dd2fd27.png)
注意:默认的编码是gbk,为防止乱码:
-
方法一(打开文件时):
fobj = open('./test.txt', 'w', encoding='utf-8')
-
方法二(写入文件时):
obj.write('hello world'.encode('utf-8'))
wb-只二进制写
01字符串
fobj = open('./test.txt', 'wb')
fobj.write('hello world')
fobj.close()
报错:
![](https://i-blog.csdnimg.cn/blog_migrate/249ee76da4deb234678d70b10bf0f6cd.png)
注意:wb写入时,要指定写入值的类型 obj.write('hello world'.encode('utf-8'))
修改后运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/67ca1d46c4b136141fbb67338195494d.png)
a-只追加写
追加:存在则在原来基础上接着写,不存在则从头写
fobj = open('./test.txt', 'a')
fobj.write('这是追加的内容'.encode('utf-8'))
fobj.close()
报错:
![](https://i-blog.csdnimg.cn/blog_migrate/9e5b04fd6165ae6233d8cc5896c38143.png)
注意:a打开模式,写入内容必须是字符串,不需要添加encode。
修改后报错:
![](https://i-blog.csdnimg.cn/blog_migrate/e004adfe82cc2e8bbbd3dea87aef6426.png)
注意:虽然是字符串类型写入的,但打开后依然显示乱码,在打开文件时使用 encoding = 'utf-8'
修改后运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/42893329a8143655e9c801b16a05824c.png)
ab-只二进制追加
fobj = open('./test.txt', 'ab')
fobj.write('\n这还是追加的内容'.encode('utf-8'))
fobj.close()
运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/4225482d1c60fcbc7039e252109af12d.png)
注意:’\n’在写入时表示换行符!
文件的读取
read()
read()表示读取全部内容,r打开模式下:read(2)读取前两个字符,rb模式下表示读取前两个字节
案例:读取test.txt文件
f = open('test.txt', 'r', encoding='utf-8') # 打开模式使用r(只读)
print(f.read(10)) # 读取10个字符
print('---------------')
print(f.read()) # 读取全部内容
f.close()
运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/8a74d64360570bd4c7b13f9b94166c05.png)
注意:第二个read()开始读取的位置为第一个read()读取结束的位置+1。
readline()
读取一行
f = open('test.txt', 'r', encoding='utf-8')
print(f.readline())
print(f.readline())
f.close()
运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/54aeeb0e2f421cf4bdf34dcd85bcbe9f.png)
注意:每行最后都会跟一个空行,想避免这个问题可以使用end=''
readlines()
按行读取所有内容并将读取到的数据存入列表中
f = open('test.txt', 'r', encoding='utf-8') # 使用r打开模式,打开文件
dataList = f.readlines() # readlines()读取文件所有内容
print(type(dataList)) # 打印存放读取数据的列表
for item in dataList: # 遍历该列表,输出文件内容
print(item, end='') # 使用end='' 避免出现空行的问题
f.close() # 关闭文件
运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/84a19c3f88219bce6300c1591ca90235.png)
补充
-
解码:decode
f = open('test.txt', 'rb') # 二进制读取 data = f.read() print(data.decode('utf-8')) # decode解码 f.close()
运行结果:
-
with关键字
使用open()函数打开文件后,容易忘记关闭文件,使用with关键字打开文件可避免因此带来的问题
with open('test.txt', 'r', encoding='utf-8') as f: print(f.read())
运行结果:
文件备份脚本
小文件
def smallFileCopy():
old_name = input('请输入要备份的文件名:')
old_nameList = old_name.split('.')
new_name = old_nameList[0] + '备份.' + old_nameList[1]
with open(old_name, 'r', encoding='utf-8') as old_file, open(new_name, 'w', encoding='utf-8') as new_file: # 要同时打开多个文件是,可以只使用一个with,多个open()之间使用逗号分隔
fileData = old_file.read()
new_file.write(fileData)
pass
pass
smallFileCopy()
运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/1132b1fc1690157661529918541c860b.png)
注意:该代码仅适用于小型文件,因为使用read()一次读取全部会消耗较大内存。
大文件
def bigFileCopy():
old_name = input('请输入要备份的文件名:')
old_nameList = old_name.split('.')
new_name = old_nameList[0] + '备份.' + old_nameList[1]
with open(old_name, 'r', encoding='utf-8') as old_file, open(new_name, 'w', encoding='utf-8') as new_file:
while True:
fileData = old_file.read(1024)
new_file.write(fileData)
if len(fileData) < 1024:
break
pass
bigFileCopy()
运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/7728e436b8cf3a4da4af7abc8cfa25b7.png)
注意:每次读取固定大小字符,避免一次读取过多内容。
文件定位
tell
获取文件指针位置(字节)
with open('test.txt', 'r', encoding='utf-8') as f:
print(f.read(6)) # 读取6个字符
print(f.tell()) # 打印文件指针位置
运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/4eb0921855a7d5abdd33660cd384a4c7.png)
注意:
- utf-8编码下:汉字所占字节数为3
- gbk编码下:汉字所占字节数为2
- 英文所占字节数,在上面两种编码下均为1个
案例中所用编码格式为utf-8,共读取6个字符,故文件指针位置在第3*6=18个字节处
truncate
f.truncate(10):保留前10个字节的内容
with open('test.txt', 'r+', encoding='gbk') as f: # gbk编码格式,每个中文占2个字节
f.truncate(10) # 字节
print('-------截取后文件的内容:-------')
print(f.read())
运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/fa5316093912656a5065bcd00536bde9.png)
seek
设置文件指针的位置
-
语法:
f.seek(offset,from)
注意:
- offset:表示偏移量(字节,为负表示向前移动)
- from:0-从头,1-从当前位置,2-从文件末尾
-
案例1:seek的简单使用
with open('test备份.txt', 'rb') as f: print(f.read(3).decode('utf-8')) f.seek(-3, 1) # 文件指针回溯3个字节 print(f.read(6).decode('utf-8'))
运行结果:
-
当文件打开方式为非二进制时,只允许从文件的开头计算相对位置。
模块
import
导入模块中所有的功能
-
导入和使用:
import time # 导入 print(time.ctime()) # 调用
运行结果:
-
首次导入模块时,系统的操作:
- 打开模块文件
- 执行该文件,将执行过程中产生的名字都丢到模块的名称空间
- 在程序中会有一个模块的名称指向模块的名称空间去
-
模块搜索路径:
-
优先搜索当前目录(自定义模块中的函数名不要和系统中的重复)
-
sys模块中搜索:
-
第三方模块默认安放位置:
- linux:/usr/local/lib/python
- windows:环境变量位置\Lib\site-package
-
-
as 起别名:
import time as t # 别名为t print(t.ctime()) # 模块名称不可使用
运行结果:
from…import
只导入其中部分函数
-
导入和使用:
from time import ctime, time # 导入两个函数,不需要添加括号 print(ctime()) # 不再需要模块名称
导入全部:
from time import * # 导入全部函数 print(ctime()) # 不再需要模块名称
运行结果:
-
首次导入模块时,系统的操作:
- 以模块为准创建一个名称空间
- 执行该模块文件,将执行过程中产生的名字都丢到模块的名称空间
- 在程序中拿到一个名字,该名字直接指向模块中的某一个名字
缺点:容易与本地文件中的函数名称冲突
os模块
-
重命名:
os.rename('test.txt', 'test_重命名.txt')
-
删除文件:
os.remove('test备份.txt')
-
创建文件夹:
-
创建一级目录:
os.mkdir('hello')
-
创建多级目录:
os.makedirs('world\hello')
-
-
删除文件夹:
-
删除空目录:
os.rmdir('hello')
-
删除非空目录:
import shutil as st st.rmtree('world')
-
-
打印当前程序目录:
print(os.getcwd())
-
遍历d盘根目录下文件名称:
-
os.listdir():
import os rs = os.listdir('d:/') for item in rs: print(item)
-
os.scandir():
with os.scandir('d:/') as sc: for rs in sc: print(rs.name)
运行结果:
注意:d盘根目录的表示方法 ‘d:/’
-
-
判断是否是目录/文件:
print(os.path.isdir('world')) # 返回值为布尔类型
注意:可以通过递归实现打印某个目录下的全部文件
-
其它的一些操作:
制作模块
制作模块实现返回两个数的和
-
模块内容:
def add(a, b): ''' 返回a与b的和 :param a: 数a :param b: 数b :return: a+b ''' return a + b # 测试 rs = add(1, 2) print('测试结果:', rs)
运行结果:
-
导入模块:
import modudelTest # 导入自定义模块 rs = modudelTest.add(1, 1) print('测试结果:', rs)
运行结果:
注意:导入模块时,其内部的测试代码也会被执行
-
模块内输出魔术变量__name__的值:
def add(a, b): ''' 返回a与b的和 :param a: 数a :param b: 数b :return: a+b ''' return a + b # 测试 print('__name__的值是:', __name__)
-
运行模块文件:
-
导入模块:
import modudelTest # 导入自定义模块
运行结果:
注意:可以看出__name__在模块内和程序内的值是不同的,我们可以通过该特征解决2中的问题
-
-
根据3中性质修改后的模块代码:
def add(a, b): ''' 返回a与b的和 :param a: 数a :param b: 数b :return: a+b ''' return a + b # 测试 if __name__ == '__main__': # 判断__name__的值决定是否运行下面的代码 rs = add(1, 2) print('测试结果:', rs)
-
__all__魔术变量:
当模块中定义了__all__的值,使用from…import * 则只能导入all中存在的函数名
-
模板内容:
__all__ = ['add', 'diff'] # 魔术变量__all__ def add(a, b): return a + b def diff(a, b): return a - b def printInfo(): return '这是输出的信息'
-
使用import导入模板:
import modudelTest # 导入自定义模块 print(modudelTest.add(1, 2)) print(modudelTest.diff(5, 4)) print(modudelTest.printInfo())
运行结果:
-
使用from…import *导入模板:
from modudelTest import * print(add(1, 2)) print(diff(5, 4)) print(printInfo())
运行结果:
报错原因:模板中定义了__all__的值为 [‘add’, ‘diff’],当私用from导入全部函数时,只可导入all中定义的函数
-
发布模块
让其他开发者安装后使用
-
新建文件夹并将模块文件移入其中:
-
文件夹中新建setup.py ,按照注释补充模板内容:
from distutils.core import setup # name 模块名称 # version 版本号 # description 描述 # author 作者 # py_modules 要发布的内容 setup(name="moduelTest", version="1.0", description="两位数加、减法、输出字符串", author="XJHui", py_modules=['modudelTest']) # 不需要写文件后缀
-
在新建文件夹下执行命令:
python setup.py build
运行结果:
-
生成压缩包:
python setup.py sdist
-
找到压缩包,分享后安装即可使用
安装模块
-
压缩包所在文件夹中执行命令:
pip install moduelTest-1.0.tar.gz
运行结果:
-
使用模块:
import modudelTest as mt print(mt.add(1, 5))
运行结果:
不足之处,欢迎留言,会及时回复,及时更正!
创作不易,感谢支持!