一、文件操作
打开文件
用于打开一个文件,创建并返回一个 file 对象
open(name[, mode[, buffering]])
-
name : 文件名称的字符串值。
-
mode : 打开文件的模式:只读,写入,追加等。这个参数是非强制的,默认文件访问模式为只读。
-
buffering : 如果 buffering 的值被设为 0,就不会有寄存。如果 buffering 的值取 1,访问文件时会寄存行。如果将 buffering 的值设为大于 1 的整数,表明了这就是的寄存区的缓冲大小。如果取负值,寄存区的缓冲大小则为系统默认。
模式 | 说明 |
---|---|
b | 二进制模式 (文本文件、视频、音乐等等都可使用该模式) 。 |
+ | 打开一个文件进行更新 (可读可写)。 |
r | 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 |
w | 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件进行写入 |
r+ | 打开一个文件用于读写。文件指针将会放在文件的开头。不能创建文件,注意指针的位置 |
w+ | 打开一个文件用于读写。如果该文件已存在则打开文件,并删除原来内容,然后在进行读写,注意指针的位置。如果该文件不存在,创建新文件。 |
rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头,注意指针的位置。 |
wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除,注意指针的位置。如果该文件不存在,创建新文件。 |
- 要注意的是python3的文件默认编码为utf-8,但文件读和写(r|w)的默认编码为gbk
- 一个我们可读的txt文本包括两个重要部分,一个是文字的编码格式,另一个是文本的读取格式。这两个要一致才可以把二进制翻译成我们可读的txt文件
- 文本文件才存在行的概念,二进制文件不存在
- 之所以存在要注意文件的指向的问题是因为文件的读取在python3里面是以流的形式的
- 要注意open() 里面的encoding默认为gbk,encode() 方法里面的 encoding 默认为utf-8
写
write()
file_obj = open('./test.txt', 'w', encoding='utf-8') # 打开文件,并把字符的编码与文件的编码方式换为utf-8,默认为gbk
file_obj.write('你好\n') # 默认的编码为gbk,在这里是utf-8
file_obj.write('世界\n')
file_obj.close() # 注意要关闭文件,以对文件进行保护
file_obj = open('./test.txt', 'wb+')
file_obj.write('sss你好,撒大大青蛙的'.encode('utf-8')) # 以utf-8编码对字符串进行编码,获得bytes类型对象
file_obj.close()
读
①file.read([size]):size指定的话则返回指定字符个数, 未指定则返回整个文件,f.read()读到文件尾时返回""(空字串),且换行符也算字符,注意文件指针的指向
②file.readline():返回一行,且这行里面末尾会自动加上换行符(\n),注意文件指针的指向
③file.readlines([size]) :返回包含size行的列表, size 未指定则返回全部行,注意文件指针的指向
④file.readable():判断file对象是否可读,当然对应的也有writable()函数
with上文管理
with 语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。
with open('./test.txt', 'r', encoding='utf-8') as file_obj:
print(file_obj.read())
f.close()
关闭文件流通道
文件备份
# 适用于小文件
def copyFile(param):
file_list = param.split('.')
new_file = './' + file_list[0] + '_copy.' + file_list[1]
old_file_obj = open(param, 'r', encoding='utf-8')
new_file_obj = open(new_file, 'w', encoding='utf-8')
new_file_obj.write(old_file_obj.read())
old_file_obj.close()
new_file_obj.close()
pass
copyFile('test.txt')
# 适用于大文件
def copyFile(param):
file_list = param.split('.')
new_file = './' + file_list[0] + '_copy.' + file_list[1]
try:
with open(param, 'r', encoding='utf-8') as old_file_obj, open(new_file, 'w', encoding='utf-8') as new_file_obj:
while True:
str_current = old_file_obj.read(1024)
new_file_obj.write(str_current)
if len(str_current) < 1024:
break
pass
pass
old_file_obj.close()
new_file_obj.close()
pass
pass
except Exception as msg:
print(msg)
pass
else:
print('复制成功')
pass
pass
copyFile('test.txt')
文件读取定位
tell()可以获得当前文件指针读取到的字节位置,不过要注意一个汉字对应两个字节
file_obj = open('./test.txt', 'w', encoding='utf-8')
file_obj.write('888 ni 你好') # 12个字节
print(file_obj.tell())
file_obj.close()
truncate()
截取文件内的指定字符
file_obj = open('./test.txt', 'r+', encoding='utf-8')
file_obj.truncate(3) # 截取文件前三个字符
print(file_obj.read()) # 读取文件
file_obj.close()
seek()
用于移动文件指针到指定位置
fileObject.seek(offset[, whence])
- offset – 偏移量,也就是代表需要移动偏移的字节数
- whence:可选,默认值为 0。给offset参数一个定义,表示要从哪个位置开始偏移;0代表从文件开头开始算起,1代表从当前位置开始算起,2代表从文件末尾算起。
with open('./test.txt', 'rb') as file_obj: # with块
file_obj.seek(2, 0)
print(file_obj.read(4).decode('gbk')) # 把读取的二进制使用gbk编码来解释
print(file_obj.tell()) # 获得当前的指针位置
file_obj.seek(-2, 1) # 报错,不可这样使用
print(file_obj.read(2).decode('gbk'))
file_obj.seek(-2, 2) # 报错
print(file_obj.read(2).decode('gbk'))
pass
注意:若没有使用二进制读写文件,则seek函数里面的whence只能为0,而其他情况会报错
例如:
with open('./test.txt', 'r') as file_obj: # r模式
file_obj.seek(2, 0) # 可以执行
print(file_obj.read(2))
print(file_obj.tell())
file_obj.seek(-2, 1) # 报错
print(file_obj.read(2))
file_obj.seek(-2, 2) # 报错
print(file_obj.read(2))
pass
with open('./test.txt', 'w') as file_obj: # w模式
file_obj.seek(2, 0) # 可以执行
file_obj.write('11')
file_obj.seek(-2, 1) # 报错
file_obj.write('11')
file_obj.seek(-2, 2) # 报错
file_obj.write('11')
pass
二、模块和包导入
模块和包的导入
- 导入一般放在文件最前面
- from……import…… 就只导入该模块或包中的部分内容或全部内容(*),要注意的是该方式在调用时只能使用默认名,就可能会造成命名冲突
- 要注意无论使用何种方式导入模块,导入模块的全部内容都会被执行。且在通过包导入模块时候会执行该模块和__init__模块
- 在只导入包时只会执行__init__模块,也就意味着无法访问除__init__模块的其他模块
- 在一次程序执行中,对相同的内容import导入就只导入一次
import time
print(time.ctime())
from time import ctime # 推荐使用
print(time.ctime())
from user.models import User # user为包名,models为模块名,User为模块内的东西
as为模块取别名
注意这里是模块名,而不是函数名
import time as myTime
print(myTime.ctime())
__name__
python的模块既可以被调用,也可以独立运行。而被调用时__name__存储的是py文件名(模块名称),独立运行时存储的是"__main__"。
__all__
它表示一个模块中允许哪些属性可以被导入到别的模块中(如:全局变量,函数,类),所以它是为了限制或者指定能被导入到别的模块的函数,类,全局变量等,如果指定了那么只能是指定的那些可以被导入,没有指定默认就是全部可以导入。
但需要注意的是__all__只影响到了 from <module> import * 这种导入方式,对于 from <module> import <member> 导入和import <module>方式并没有影响,仍然可以从外部导入。
模块搜索路径
当解释器遇到import关键字,会优先搜索当前录下是否有这个名字的模块,所以在模块命名的时候不要与系统中的模块有重名(自定义的文件优先级高);如果当前目录没有,则到环境变量中搜索;如果都找不到,则搜索默认路径,window的第三方模块安装位置在python安装目录下的lib/site-packages/目录下。
包和文件夹
- 包和文件夹差异不大,只是包内有一个__init__.py文件。也就是说如果在文件夹里面定义一个__init__.py文件文件夹就变成了一个包
- 一个项目里可有多个包,一个包里面可以放多个模块
包的__init__.py文件
- __init__模块会在导入包时自动执行,该模块里面一般放一些初始化函数、变量等等,而函数、变量等可通过包名来调用。
- 它也可配合__all__来使用
模块的循环导入问题
大型的python项目中,需要很多python文件,由于架构不当,可能会出现模块之间的相互导入,而严重的会导致程序崩溃。不过有两种避免方法:①重新架构,代价太大②将导入的语句放到调用的地方以避免导致程序崩溃③使用__name__ 以避免程序逻辑混乱
例如1(下面的程序因循环导入模块而导致程序崩溃):
# 该文件为index.py
from hello import foo1
def foo():
print('index---- foo')
# 该文件为hello.py,且为入口文件
from index import foo
def foo1():
print('hello---- foo1')
foo1()
# 输出结果
ImportError: cannot import name 'foo' from partially initialized module 'index' (most likely due to a circular import)
下面为解决方法:
# 该文件为index.py
def foo():
from hello import foo1
print('index---- foo')
# 该文件为hello.py,且为入口文件
from index import foo
def foo1():
print('hello---- foo1')
foo1()
# 输出结果
hello---- foo1
例如2(下面的程序因多次导入模块而导致程序逻辑混乱):
# 该文件为index.py
def foo():
print('index---- foo')
from hello import foo1
foo1()
# 该文件为hello.py,且为入口文件
from index import foo
def foo1():
print('hello---- foo1')
def foo2():
print('hello---- foo2')
foo()
foo1()
foo2()
# 输出结果
hello---- foo1
hello---- foo2
index---- foo
hello---- foo1
hello---- foo2
index---- foo
hello---- foo1
hello---- foo1
下面为解决方法:
# 该文件为index.py
def foo():
print('index---- foo')
from hello import foo1
foo1()
# 该文件为hello.py,且为入口文件
from index import foo
def foo1():
print('hello---- foo1')
def foo2():
print('hello---- foo2')
foo()
if __name__ == '__main__': # 防止循环导入模块
foo1()
foo2()
# 输出结果
hello---- foo1
hello---- foo2
index---- foo
hello---- foo1
三、os模块
os模块是提供一些系统级别的操作命令(如:文件重命名等),下面介绍一些常用的方法
路径操作
os.path.isabs()
判断路径是否为绝对路径
import os
print(os.path.isabs(r'C:\Users\12133\Documents\WindowsPowerShell')) # True
os.path.dirname()
它与getcwd函数类似,获得传入参数的上级目录,__file__的值为当前文件的绝对路径
import os
print(os.path.dirname(__file__)) # 这里输出的结果为当前文件的工作目录
print(__file__)
# 输出结果
F:\pycharm\pythonProject
F:\pycharm\pythonProject\index.py
os.getcwd()
用于返回当前文件的上级目录,没有参数
import os
print(os.getcwd()) # F:\pycharm\pythonProject
os.path.abspath()
将传入的路径转换为绝对路径
import os
print(os.path.abspath('./index.py'))
# 输出结果
F:\pycharm\pythonProject\index.py
os.path.join()
路径拼接,用于将多个路径组合后返回
import os
path = os.path.join(os.getcwd(), 'hello.txt') # 目录的拼接,注意这里是path下面的join
print(path)
os.path.split()
路径分割获得文件名,用于将一个路径分割并组成一个元组后再返回
import os
print(os.path.split(r'./index.py'))
print(os.path.split(r'F:\pycharm\pythonProject/index.py'))
# 输出结果
('.', 'index.py')
('F:\\pycharm\\pythonProject', 'index.py')
os.path.splitext()
路径分割获得文件拓展名,用于将一个路径分割并组成一个元组后再返回
import os
print(os.path.splitext(r'./index.py'))
print(os.path.splitext(r'F:\pycharm\pythonProject/index.py'))
# 输出结果
('./index', '.py')
('F:\\pycharm\\pythonProject/index', '.py')
os.path.isdir()&os.path.isfile()
判断是否是目录或文件
import os
with os.scandir('./') as entries: # 使用with来处理资源访问操作
for entry in entries:
if os.path.isdir(entry): # 判断是否为文件夹
print('文件夹名:{}'.format(entry))
pass
elif os.path.isfile(entry): # 判断是否为文件
print('文件名:{}'.format(entry))
pass
文件操作
os.rename()
修改文件名
import os
os.rename( 'test.txt' , 'tests.txt')
os.remove()
删除文件
import os
os.remove( 'tests.txt ')
os.mkdir()
创建文件夹
import os
os.mkdir('myTest') # 它只能创建一级目录
os.makedirs('d:/myTest/test') # 它可以创建多级目录
os.rename()&shutil.rmtree()
删除文件夹,os.rename()只能删除空文件夹,shutil.rmtree()用于删除多级文件夹
import os
os.rmdir('myTest') # 只能删除空目录
import shutil
shutil.rmtree('d:/myTest') # 删除多级目录
os.chdir()
切换目录
import os
os.chdir('./venv') # 切换目录
print(os.getcwd())
os.listdir()&os.scandir()
返回目录所在的文件或文件夹列表,只返回一级目录
import os
print(os.listdir('./')) # 只打印一级,且返回一个列表
print(os.scandir('./')) # 返回一个迭代器对象
with os.scandir('./') as fileValue: # with尽量与资源访问一起使用
for value in fileValue:
print(value) # 只打印一级对象
pass
pass
四、自定义模块发布与安装
在python里面,一个模块就是一个python文件。
自定义模块发布
需要发布的模块(simpleCompute.py):
def addition(x, y):
return x + y
def minus(x, y):
return x - y
className = '一班'
__all__ = ['addition', 'className']
if __name__ == '__main__': # 测试时执行
print('这里是测试用例')
print('__name__值为%s' % __name__)
pass
若要发布模块的话,要先创建一个文件夹,再把写好的模块放入到文件夹内,然后再在该文件夹内创建一个setup.py文件,内容如下,然后再在终端内进入该文件夹目录内,输入python setup.py build(构建模块),然后会在该文件夹内生成一个build文件夹,再在该文件夹内输入python setup.py sdist,来生成压缩包并会在该文件夹内生成一个dist文件夹。
当然我们也可使用在该文件内输入tree命令来查看这个文件的目录结构
setup.py文件:
from distutils.core import setup
# name模块名称
# version版本号
# description 描述
# author作者
# py_modules要发布的内容
setup(name="simpleCompute", version="1.0", description=”文件的简单计算模块"", autbor="xMan", py_modules=['simpleCompute'])
自定义模块安装
在pycharm里面的终端里面输入pip install 压缩文件即可安装模块
pip install simpleCompute-1.0.tar.gz
五、sys模块
sys模块为python环境模块
sys.path
导入包的搜索路径
import sys
print(sys.path)
# 输出结果
['F:\\pycharm\\pythonProject', 'F:\\pycharm\\pythonProject', 'F:\\pycharm\\PyCharm 2020.2.3\\plugins\\python\\helpers\\pycharm_display', 'F:\\python\\python39.zip', 'F:\\python\\DLLs', 'F:\\python\\lib', 'F:\\python', 'F:\\pycharm\\pythonProject\\venv', 'F:\\pycharm\\pythonProject\\venv\\lib\\site-packages', 'F:\\pycharm\\PyCharm 2020.2.3\\plugins\\python\\helpers\\pycharm_matplotlib_backend']
sys.version
import sys
print(sys.version)
# 输出结果
3.9.0 (tags/v3.9.0:9cf6752, Oct 5 2020, 15:34:40) [MSC v.1927 64 bit (AMD64)]
六、time模块
time()
返回当前的时间戳(秒),浮点类型
import time
print(time.time())
# 输出结果
1606561264.2610068
sleep()
休眠一段时间
import time
print(time.time())
time.sleep(3)
print(time.time())
# 输出结果
1606561596.5063899
1606561599.5070715
ctime()
若有参数(时间戳)则把参数转成字符串(该格式无法修改),若无参数则返回当前日期(字符串类型)
import time
second = time.time()
print(time.ctime(second))
print(time.ctime())
# 输出结果
Sat Nov 28 19:09:59 2020
Sat Nov 28 19:09:59 2020
strptime()
time.strptime(string, format)
将字符串转换为元组类型
import time
print(time.strptime('2020年10月19日', '%Y年%m月%d日'))
# 输出结果
time.struct_time(tm_year=2020, tm_mon=10, tm_mday=19, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=0, tm_yday=293, tm_isdst=-1)
localtime()
time.localtime([ sec ])
若有参数(时间戳)则把参数转成元组时间,若无参数则返回当前日期(元组类型)
import time
second = time.time()
print(time.localtime(second)) #
print(time.localtime())
# 输出结果
time.struct_time(tm_year=2020, tm_mon=11, tm_mday=28, tm_hour=19, tm_min=12, tm_sec=11, tm_wday=5, tm_yday=333, tm_isdst=0)
time.struct_time(tm_year=2020, tm_mon=11, tm_mday=28, tm_hour=19, tm_min=12, tm_sec=11, tm_wday=5, tm_yday=333, tm_isdst=0)
mktime()
将元组时间转换为时间戳(浮点型)
import time
time_tuple = time.localtime()
print(time.mktime(time_tuple))
# 输出结果
1606562577.0
strftime()
time.strftime(format[, t])
将元组时间转成字符串(该格式可以自定义)
import time
time_tuple = time.localtime()
print(time.strftime('%Y年%m月%d日'))
print(time.strftime('%Y年%m月%d日', time_tuple))
# 输出结果
2020年11月28日
2020年11月28日
下面的图为有参数的各种函数转换情况(若没有参数则直接获得当前的时间)
七、datetime模块
datetime 比 time 高级了不少,可以理解为 datetime 基于 time 进行了封装,提供了更多实用的函数
datetime.now()
返回当前时间
import datetime
now = datetime.datetime.now()
print(now)
# 输出结果
2020-11-28 20:15:44.940523
timedelta()
timedelta(Δ)可以方便实现日期(date实例、time实例、datetime实例)之间的运算。
import datetime
timedel = datetime.timedelta(days=2)
print(timedel) # 时间间隔
now = datetime.datetime.now()
print(now) # 输出当前时间
print(now + timedel) # 输出经处理的时间
# 输出结果
2 days, 0:00:00
2020-11-28 20:09:47.057137
2020-11-30 20:09:47.057137
八、random模块
random()
返回一个0到1的小数
import random
print(random.random())
# 输出结果
0.7519760407323736
randint()
返回一个整数,包含边界
import random
print(random.randint(1, 3))
choice()
random.choice(sequence)
随机选择序列里的某个值(抓阄)
import random
list1 = ['mike', 'li', 'hua', 'ming', 'wang']
print(random.choice(list1))
# 输出结果
li
shuffle()
random.shuffle (list)
将列表里的值顺序打乱,没有返回值(洗牌)
import random
list1 = ['mike', 'li', 'hua', 'ming', 'wang']
random.shuffle(list1)
print(list1)
# 输出结果
['mike', 'wang', 'ming', 'hua', 'li']
九、hashlib模块
hashlib模块提供一些加密的算法
md5()
import hashlib
str1 = 'li,你好吗?'
md5 = hashlib.md5(str1.encode('utf-8')) # 注意这里的编码格式
print(md5.hexdigest()) # 将加密结果以十六进制的方式输出
print(md5)
# 输出结果
3f413c7523a0bad284c6e5b84e2dc0fb
<md5 _hashlib.HASH object @ 0x000001DAA0652B50>
本文只用于个人学习与记录