1. time模块
1.1 time的格式
三种格式:
1. 时间戳
2. 按照某种格式显示的时间
3. 结构化的时间
时间戳: 从1970年到代码执行时间点期间经历过的秒数, 调用time.time()
import time
print(time.time())
>> 1612284368.302347
格式化显示时间: 调用time.strftime()
import time
print(time.strftime('%Y-%m-%d %H:%M:%S'))
>> 2021-02-03 00:48:35
结构化时间: 调用time.localtime()
import time
print(time.localtime()) # time.localtime()显示当前时间的具体信息
>> time.struct_time(tm_year=2021, tm_mon=2, tm_mday=3, tm_hour=0, tm_min=52, tm_sec=34, tm_wday=2, tm_yday=34, tm_isdst=0)
# 可以赋值给变量, 然后通过变量名.key去获得value
import time
info = time.localtime()
print(info.tm_year)
>> 2021
print(info.tm_mon)
>> 2
1.2 不同格式的应用场景
1. 时间戳: 用于时间间隔的计算
2. 格式化显示时间: 按照某种格式展示
3. 结构化时间: 用于单独获取当前时间的某部分的value
1.3 不同格式之间的转换
1. 结构化时间 ---time.mktime(结构化时间)---> 时间戳格式
import time
print(time.localtime())
>> time.struct_time(tm_year=2021, tm_mon=2, tm_mday=3, tm_hour=1, tm_min=19, tm_sec=47, tm_wday=2, tm_yday=34, tm_isdst=0)
timestamp=time.localtime()
print(time.mktime(timestamp))
>> 1612286387.0
2. 时间戳 ---time.localtime(时间戳)---> 结构化时间
import time
s_time = time.time()
print(s_time)
>> 1612286616.320777
print(time.localtime(s_time))
>> time.struct_time(tm_year=2021, tm_mon=2, tm_mday=3, tm_hour=1, tm_min=23, tm_sec=36, tm_wday=2, tm_yday=34, tm_isdst=0)
3. 结构化时间 ---time.strftime()---> 格式化字符串时间
import time
l_time = time.localtime()
print(l_time)
>> time.struct_time(tm_year=2021, tm_mon=2, tm_mday=3, tm_hour=1, tm_min=32, tm_sec=29, tm_wday=2, tm_yday=34, tm_isdst=0)
print(time.strftime('%Y-%m-%d %H:%M:%S',l_time))
>> 2021-02-03 01:32:29
4. 格式化字符串时间 ---time.strptime()---> 结构化时间
import time
f_time = time.strftime('%Y-%m-%d %H:%M:%S')
print(f_time)
>> 2021-02-03 01:35:04
s_time = time.strptime(f_time, '%Y-%m-%d %H:%M:%S')
print(s_time)
>> time.struct_time(tm_year=2021, tm_mon=2, tm_mday=3, tm_hour=1, tm_min=35, tm_sec=4, tm_wday=2, tm_yday=34, tm_isdst=-1)
注意: 格式化字符串的时间格式与时间戳不能直接转换, 需要通过结构化时间进行转换
案例: 假设当前时间为'1990-07-10 10:10:10', 如果计算7天后的时间
实现过程: 把格式化时间 > 转成结构化时间 > 时间戳 > 进行时间运算 > 转回时间戳 > 转回格式化时间
import time
f_time = '1990-07-10 10:10:10'
# 第一步: 格式化字符串时间, 转成结构化时间
s_time = time.strptime(f_time,'%Y-%m-%d %H:%M:%S')
print(s_time) # >> time.struct_time(tm_year=1990, tm_mon=7, tm_mday=10, tm_hour=10, tm_min=10, tm_sec=10, tm_wday=1, tm_yday=191, tm_isdst=-1)
# 第二步: 结构化时间, 转成时间戳
time_stamp = time.mktime(s_time)
print(time_stamp) # >> 647575810.0
# 第三步: 时间戳+7天
new_time_stamp = time_stamp + 7 * 86400
print(new_time_stamp) # >> 648180610.0
# 第四步: 将新的时间戳, 转换成新的结构化格式
new_s_time = time.localtime(new_time_stamp)
print(new_s_time) # >> time.struct_time(tm_year=1990, tm_mon=7, tm_mday=17, tm_hour=10, tm_min=10, tm_sec=10, tm_wday=1, tm_yday=198, tm_isdst=0)
# 第五步: 将新的结构化格式, 转成最终的新的格式化字符串格式
new_f_time = time.strftime('%Y-%m-%d %H:%M:%S',new_s_time)
print(new_f_time) # >> 1990-07-17 10:10:10
# 结果
# '1990-07-10 10:10:10' ---> '1990-07-17 10:10:10'
1.4 time模块支持的其他格式
import time
print(time.asctime())
>> Wed Feb 3 02:06:54 2021
2. datetime模块
2.1 用于获取当前时间
import datetime
print(datetime.datetime.now())
>> 2021-02-03 01:08:12.385710 # 注意: datatime获取时间的结果是datetime对象而不是字符串
2.2 进行时间的运算(主要的作用)
案例1: 计算5天后的时间
import datetime
print(datetime.datetime.now())
>> 2021-02-03 01:10:46.131210
print(datetime.datetime.now()+datetime.timedelta(days=5)) # days=5表示5天后
>> 2021-02-08 01:10:46.131210
案例2: 计算3天前的时间
import datetime
print(datetime.datetime.now())
>> 2021-02-03 01:11:56.062510
print(datetime.datetime.now()+datetime.timedelta(days=-3)) # days=-3表示3天前
>> 2021-01-31 01:11:56.062510
注意: datetime进行时间的运算不支持年, 没有此功能, 不过可以用days=365*3(计算3年后的时间)来代替
2.3 时间戳转成格式化字符串格式
好处: 一步到位
缺点: 无法指定格式化的格式
import datetime, time
s_time = time.time()
print(s_time) # >> 1612289400.193677
print(datetime.datetime.fromtimestamp(s_time)) # >> 2021-02-03 02:10:00.193677
3. random模块
取随机值
import random
print(random.random()) # 0-1之内的小数, 开区间
>> 0.4848350985621943
print(random.uniform(1,3)) # m,n, 指定范围内的小数, 开区间
>> 2.4436476444386885
print(random.randint(1,3)) # 闭区间
>> 3
print(random.randrange(1,3)) # 左闭又开
>> 2
print(random.choice([1,2,[3,4],'a'])) # choice()中放一个列表, 每次会从列表中随机取出一个元素
>> 1
print(random.sample([1,2,3,[11,22]],2)) # sample()放一个列表, 每次按照后面指定的数字, 从列表中随机取出2个元素, 并且以列表格式返回, 注意, sample()必须指定随机取出值的个数
>> [3, 2]
list1 = [1,2,3,4,5]
print(random.shuffle(list1)) # random.shuffle()会将列表顺序随机打乱, 并且会修改源列表
print(list1)
>> [2, 5, 3, 1, 4]
案例: 生成随机验证码, 6位大写字母和数字的组合
import random
res = '' # 初始化一个空字符串
for i in range(6): # 6为随机字符串, 所以循环6次, 每次从大写字母和数字中随机random.choice()取出来一个, 和res做拼接
alpha = chr(random.randint(65,90)) # chr('数字'), 将对应的数字按照ASCII表的顺序转成字符串, 大写字母范围是65-90, 所以random.randint()取出一个数字, 然后转成字符串
num = str(random.randint(0,9)) # str(), 将数字转成字符格式, 因为字符串只能和字符串拼接, 不能和数字拼接
alnum = random.choice([alpha,num]) # 得到随机的大写字母和数字, 加入到random.choice(), 每次随机取出一个, 和res拼接
res += alnum
print(res)
4. os模块
4.1 os.getcwd()
os.getcwd() --> 获取当前工作目录,即当前Python脚本工作的目录路径
import os
dir = os.getcwd()
print(dir)
>> C:\Users\David\PycharmProjects\pythonProject\模块
4.2 os.chdir()
os.chdir() --> 改变当前脚本工作目录;相当于shell下cd
os.chdir(r"C:\Users\David\PycharmProjects\pythonProject\练习")
print(os.getcwd())
>> C:\Users\David\PycharmProjects\pythonProject\练习
4.3 os.makedirs('dirname1/dirname2')
os.makedirs('dirname1/dirname2') --> 生成多层递归目录, 支持绝对路径和相对路径
4.4 os.curdir 和 os.pardir
import os
print(os.curdir) >> . # 返回 '.', 表示当前工作目录
print(os.pardir) >> .. # 返回, '..', 表示上级工作目录
4.5 os.removedirs('dir')
os.removedirs('dirname1') --> 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
4.6 os.mkdir('dirname')
os.mkdir('dirname') --> 生成单级目录;相当于shell中mkdir dirname
4.7 os.rmdir('dirname')
os.rmdir('dirname') --> 删除单级空目录,若目录不为空则无法删除,报错
4.8 os.listdir('dirname')
os.listdir('dirname') --> 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
import os
print(os.listdir(r'C:\Users\David\PycharmProjects\pythonProject\s14\模块'))
>> ['os模块.py', 'random模块.py', 'time模块.py', '__pycache__', '练习.py']
print(os.listdir('.'))
案例: 统计一个目录的大小
1. os.listdir, 列出目标目录的子目录和文件
2. 从上一步结果的列表, for循环取值, 每一进行判断, 取出来的是目录还是文件, 如果是文件, 直接os.path.getsize()取文件大小, 然后加到sum求和
3. 如果是目录, 则递归执行os.listdir
#! /usr/bin/python3
import os
target=os.getcwd()
def get_size(target):
dir = os.listdir(target)
sum_size = 0
for item in dir:
j = '{target}/{item}'.format(target=target,item=item)
if os.path.isfile(j):
res = os.path.getsize(j)
sum_size += res
else:
sum_size += get_size(j)
return sum_size
info = get_size(target)
print(info)
4.9 os.remove()
os.remove() --> 删除一个文件
4.10 os.rename("oldname","newname")
os.rename("oldname","newname") --> 重命名文件/目录
4.11 os.stat('path/filename')
os.stat('path/filename') --> 获取文件/目录信息
4.12 os.system("bash command")
os.system("bash command") --> 运行shell命令,具体要看Python运行在什么平台
4.13 os.environ
os.environ --> 获取系统环境变量
结果是字典格式, 并且key和value都是字符串
在整个程序任何地方都能获取到的变量
添加变量到environ
import os
env = os.environ
env['username']='admin'
print(env)
>> 'USERNAME': 'admin'
用途: 程序运行中, 某个代码片段产生了一个变量, 并且希望这个变量也能被其他文件中的代码访问到, 那么就可以把这个变量加入到environ中
比如, 一个用户登录, 那么在登录的运行文件中, 可以获取用户名字, 这时如果其他的文件也要调用这个用户名, 那么可以把用户名添加到系统环境变量里
4.14 os.path.abspath(path)
os.path.abspath(path) --> 返回path规范化的绝对路径
import os
print(__file__)
>> C:/Users/David/PycharmProjects/pythonProject # Pycharm显示
print(os.path.abspath(__file__))
>> C:\Users\David\PycharmProjects\pythonProject # Windows规范
4.15 获取文件的dirname和basename
import os
print(os.path.dirname(r'a/b/c/d.txt')) >> a/b/c
print(os.path.basename(r'a/b/c/d.txt')) >> d.txt
os.path.split(path)
import os
print(os.path.split(r'a/b/c/d.txt'))
>> ('a/b/c', 'd.txt') # 结果以元组形式返回
4.16 目录和文件的判断
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
4.17 os.path.join(path1[, path2[, ...]])
os.path.join(path1[, path2[, ...]]) --> 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
import os
print(os.path.join('a','b','c','d.txt'))
>> a\b\c\d.txt
4.18 os.path.normpath()
os.path.normpath() --> 规范化路径
import os
print(os.path.normpath('a/b/c/d/../..'))
>> a\b
获取一个路径的上上级目录
import os
print(os.path.dirname(os.path.dirname('a/b/c/d'))) # Python2和Python3通用
>> a/b
4.19 pathlib模块
Python3.5以后推出的用来处理路径的模块
或者父级目录
from pathlib import Path
dir = Path(__file__)
par = dir.parent.parent.parent
print(par)
>> C:\Users\David\PycharmProjects\pythonProject
路径拼接
from pathlib import Path
dir1 = Path('a/b/c')
dir2 = 'd/e.txt'
print(dir1 / dir2)
>> a\b\c\d\e.txt
5 sys模块
5.1 sys.argv
在程序中接收执行程序时传入的参数, 类似Shell的位置参数
sys.argv 表示所有参数, 包括程序文件本身, 结果为一个列表
C:\Users\David\PycharmProjects\pythonProject\模块\sys模块.py
import sys
print(sys.argv)
print(sys.argv[0])
print(sys.argv[1])
print(sys.argv[2])
C:\Users\David\PycharmProjects\pythonProject\模块>python38 sys模块.py 1 2 3
['sys模块.py', '1', '2', '3']
sys模块.py
1
2
案例: 文件拷贝程序
import sys
src_file = sys.argv[1]
dest_file = sys.argv[2]
# 中间可以通过条件判断来显示输入的源文件和目标文件
with open(r'%s'%(src_file), mode = 'bt') as read_f, \
open(r'%s'%(dest_file), mode = 'wb') as write_f:
for line in read_f:
write_f.write(line)
6 打印进度条功能
进度条格式:
1. 进度条宽度固定
2. 随着进度增加, 百分比随之增加
[##### ] %10
[########### ] %30
原理:
动态的进度条实际都用每一次打印的静态效果模拟出来的
用新的进度条替换旧的进度条, 因为速度非常快, 所以肉眼是无法识别的
[# ]
[## ]
[### ]
[#### ]
1. 实现固定进度条
print('[%-50s]'%('#')) # 50表示进度条宽度, "-"左对齐
>> [# ]
2. 实现百分号
print('[%-50s] %s%%'%('#',100))
>> [# ] 100%
3. for循环, 实现每次打印一个#, 一共打印50次
res = ''
for i in range(50):
res += '#'
print('[%-50s]'%(res))
>>
[# ]
[## ]
[### ]
...
4. 实现不换行打印
res = ''
for i in range(50):
res += '#'
print('[%-50s]'%(res),end='')
>> [# ][## ]... #此时, 所有的进度条都会在一行打印
5. 实现每次打印时, 都在行首打印, 替换之前的打印结果
res = ''
for i in range(50):
res += '#'
print('\r[%-50s]'%(res),end='') # \r表示每次都在行首打印
6. 添加打印时间间隔, 便于观看输出效果
import time
res = ''
for i in range(50):
res += '#'
print('\r[%-50s]'%(res),end='')
time.sleep(0.5)
7. 模拟根据下载进度, 实现进度条打印
import time
recv_size = 0 # 初始化接受的数据
total_size = 100000 # 数据总大小
while recv_size < total_size:
time.sleep(0.5) # 添加时间间隔, 每0.5秒下载1024字节, 类似模拟下载速度
recv_size += 1024 # 模拟每次下载一个字节
print(recv_size)
>> # 此时执行会一次显示每次下载后的接受数据量的大小
1024
2048
3072
4096
5120
...
8. 通过打印进度条显示下载速度
percent = recv_size / total_size # 每打印进度条之前, 计算接收到的数据占总数据的百分比
hash_num = int(50 * percent) # 定义宽度为50, 那么最多50个#, 乘百分比得到每次接受完应该显示#的个数, 然后用int取整, 因为百分之会存在小数
import time
recv_size = 0 # 初始化接受的数据
total_size = 100000 # 数据总大小
while recv_size < total_size:
time.sleep(0.01) # 添加时间间隔, 每0.5秒下载1024字节, 类似模拟下载速度
recv_size += 1024 # 模拟每次下载1024个字节
# 打印进度条
percent = recv_size / total_size
hash_num = int(50 * percent) * '#' # int()后的结果是应该打印的#的个数, 再*'#'就会得到n个#
print('\r[%-50s]' % (hash_num), end='')
9. 添加百分比显示
import time
recv_size = 0 # 初始化接受的数据
total_size = 100000 # 数据总大小
while recv_size < total_size:
time.sleep(0.01) # 添加时间间隔, 每0.5秒下载1024字节, 类似模拟下载速度
recv_size += 1024 # 模拟每次下载1024个字节
# 打印进度条
percent = recv_size / total_size
hash_num = int(50 * percent) * '#'
print('\r[%-50s] %d%%' % (hash_num,int(percent*100)), end='')
10. 每次下载数量的控制
如果总数量为1025, 而每次接受1024, 那么第一次下载会下载1024, recv_size变成1024, while循环条件判断后, 会进行下一次下载, 再下载1024个字节
这样recv_size就变成了2048个字节, 那么第二次计算百分比就超过了总的数据量, 变成199%.
因此, 需要控制每次下载的数量, 防止超出总的范围
方法1: 每次计算中百分比后, 对百分之进行判断, 如果大于1, 那么强项转换成1, 这样最后一次无论接受了多少数据, 最后进度条输出的都是100%
方法2: 每次进入while循环后, 再判断一次total_size和recv_size的差值, 如果差值小于1024, 那么recv_size就+=差值, 如果大于1024, 那么还是+=1024
方法1:
import time
recv_size = 0 # 初始化接受的数据
total_size = 1025 # 数据总大小
while recv_size < total_size:
time.sleep(1) # 添加时间间隔, 每0.5秒下载1024字节, 类似模拟下载速度
recv_size += 1024 # 模拟每次下载1024个字节
# 打印进度条
percent = recv_size / total_size
if percent > 1:
percent = 1
hash_num = int(50 * percent) * '#'
print('\r[%-50s] %d%%' % (hash_num,int(percent*100)), end='')
方法2:
import time
recv_size = 0 # 初始化接受的数据
total_size = 1025 # 数据总大小
while recv_size < total_size:
time.sleep(1) # 添加时间间隔, 每0.5秒下载1024字节, 类似模拟下载速度
diff_size = total_size - recv_size
if diff_size < 1024:
recv_size += diff_size
else:
recv_size += 1024 # 模拟每次下载1024个字节
# 打印进度条
percent = recv_size / total_size
hash_num = int(50 * percent) * '#'
print('\r[%-50s] %d%%' % (hash_num,int(percent*100)), end='')
11. 将打印进度条做成功能
import time
def progress(percent):
hash_num = int(50 * percent) * '#'
print('\r[%-50s] %d%%' % (hash_num, int(percent * 100)), end='')
recv_size = 0 # 初始化接受的数据
total_size = 102500 # 数据总大小
while recv_size < total_size:
time.sleep(0.05) # 添加时间间隔, 每0.5秒下载1024字节, 类似模拟下载速度
diff_size = total_size - recv_size
if diff_size < 1024:
recv_size += diff_size
else:
recv_size += 1024 # 模拟每次下载1024个字节
# 打印进度条
percent = recv_size / total_size
progress(percent)
7 shutil模块
用于文件处理
- 将文件内容拷贝到另一个文件中
import shutil
shutil.copyfileobj(open('random模块.py', 'r'), open('random模块.bak.py', 'w'))
- 拷贝文件
shutil.copyfile('f1.log', 'f2.log') # 目标文件会自动创建
- 只把源文件的权限拷贝给目标文件, 目标文件的内容, 属主, 属组不变
shutil.copymode('f1.log', 'f2.log') #目标文件必须存在
- 只把源文件的状态信息拷贝给目标文件, 包括: mode bits, atime, mtime, flags
shutil.copystat('f1.log', 'f2.log') #目标文件必须存在
- 拷贝文件和权限
shutil.copy('f1.log', 'f2.log')
- 拷贝文件和状态信息
shutil.copy2('f1.log', 'f2.log')
- 打包, 解包, 压缩, 解压缩
将 /data/下的文件打包并压缩到当前程序文件运行的目录
# root_dir表示要打包的路径
import shutil
shutil.make_archive("data.bak","gztar",root_dir="/data")
解包解压缩
t=tarfile.open('/tmp/data.tar','r')
t.extractall('/opt')
t.close()
网友评论