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