- 作者:leo__programmer
- 声明:版权所有,转载请注明出处
- 收藏:查看更多精彩内容
前言
在实际开发中,经常需要对文件或者目录进行读取、遍历、修改等操作,目录也称文件夹,用于分层保存文件。通过目录可以分门别类地存放文件。我们也可以通过目录快速找到想要的文件。
1、打开文件
1.1 从文件中读取内容
python提供了一个open()函数,可以打开一个文件读取内容,主要的参数1:文件路径,参数2:打开模式(r读取、w写入),在python交互式模式下可以使用help(open) 打开帮助,查看用法。
**注意:**windows中存路径的文件名,定义字符串存文件名的时候,字符串前面加个r, 避免特殊字符被转义,具体用法为r“文件路径”
# 示例代码
file_name = r"C:\Users\file01.txt"
# 创建文件对象
fobj = open(file_name,mode="r",encoding="UTF-8") # 为了方便操作 定义一个变量
# 获取数据的方法一
content = fobj.read() # read()默认读所有
print(content)
# 按行读 通过循环遍历文件内容
for i in fobj: # i 代表文件中每一行的内容 处理日志
print(i)
fobj.close() # 使用结束后不要忘记关闭文件
# 打开文件的另一种写法
with open(file_name,mode="r",encoding="UTF-8") as fobj:
for i in fobj:
print(i)
2、OS模块
在 python 中可以使用使用内置的os模块实现操作文件和目录,能够以简洁高效的方式完成这些操作。常见的操作整理如下:
- 文件夹操作:包括文件夹的创建、修改(改名/移动),查询(查看、遍历)、删除等。
- 文件操作:包括文件的创建、修改、读取、删除等。
- 路径操作:文件夹或文件的路径操作,如绝对路径,文件名与路径分割,扩展名分割等
2.1 获取文件/目录方法
os.walk() 方法是一个简单易用的文件、目录遍历器,可以帮助我们高效的处理文件、目录方面的事情。它直接返回的是一个生成器, 返回的是文件的内存地址,想看到的具体的信息需要循环遍历。
语法格式:os.walk(目录名称)
# 代码示例
import os
directory = r"C:\北京"
resqult = os.walk(directory)
# 循环遍历 返回的是递归目录 每个目录是一个元组数据 0索引是路径 1索引是子目录 2索引是文件名
# 获取文件名循环遍历 使用0索引和2索引做拼接
for i in resqult:
print(i)
# 如何拿数据 使用元组下标
print("目录名称:%s" % i[0])
print("文件名称:%s" % i[-1])
# 第二种写法 分别定义3个变量 获取元组中3个索引的数据
for i,j,k in resqult:
print("目录名称:",i)
print("文件名称:",k)
print(resqult)
2.2 文件重命名
做文件重命名 os模块提供了一个现成的方法 可以用rename()方法
os.rename(源文件,新名)
# 为了避免出错 源文件建议写绝对路径
字符串操作方法示例1、获取某个目录下字符串以.txt结尾的文件 ,方法为字符串.endswith(.txt)。
示例2、字符串替换的方法 字符串.replace(旧,新)
2.3 字符串操作的一些方法
# 示例1
str.endswith(".txt")
# 示例2
.replace(旧,新)
# .jpg结尾的文件名加时间 传统的做法 截取 字符串.split(".") 用点分割字符串 根据下标取值后再做拼接
# 如何获取时间 datetime.datetime.now().strftime("%Y-%m-%d))
----------------------------------------python做持久化保存的模块------------------------------------------------------
3、pickle模块
pickle模块的优势,存入取出保持数据类型不变。
# 写入数据
# data_01 = ["1111","2222","22233123"]
# with open(r"e:\\file033",mode="wb") as fobj:
# pickle.dump(data_01,fobj)
#
# # 读取数据
# with open(r"e:\\file033",mode="rb") as fobj:
# new_data01 = pickle.load(fobj)
# print(new_data01)
# print(type(new_data01))
4、python操作目录文件代码示例
import os
import datetime
directory = r"d:\PycharmProjects\pythonProject\北京"
# 递归获取指定目录下的文件路径
def getFileName(directory):
# 创建列表 用来储存获取到的文件
file_list = []
# 遍历目录
for dir_name,sub_dir_list,file_name_list in os.walk(directory):
if len(file_name_list) > 0:
for f_name in file_name_list:
# 拼接目录和文件名
full_file_name = dir_name + "\\" + f_name
file_list.append(full_file_name)
return file_list
# 文件重命名 .txt ----> .jpg
# 该字符串方法不是一个通用的方法 需要结合实际需求进行替换
def fileRename():
# 调用遍历目录的方法
file_list = getFileName(directory)
for src_file in file_list:
# 获取.txt结尾的文件
if src_file.endswith(".txt"):
new_file = src_file.replace(".txt",".jpg") # 替换
os.rename(src_file,new_file) # 重命名
# 重命名——— 文件名_YYYY_MM_DD。jpg
def fileRenameAddTime():
file_list = getFileName(directory)
now = datetime.datetime.now().strftime("%Y_%m_%d")
for src_file in file_list:
old_name = src_file.split(".")[0]
suffix = src_file.split(".")[1]
new_file = old_name + "_" + now + "." + suffix
os.rename(src_file,new_file)
if __name__ == '__main__':
fileRenameAddTime()
5、常用案例
5.1 案例一:统计web UV
def webUV(webLog):
clientIP_list = []
with open(webLog, mode="r") as fobj:
for line in fobj:
# 取客户端IP
client_IP = line.split()[0]
clientIP_list.append(client_IP)
# 统计各IP次数
for ip in set(clientIP_list):
print("客户端地址: %s, 次数: %s" % (ip, clientIP_list.count(ip)))
if __name__ == '__main__':
web_log_file = input("web日志: ").strip()
webUV(webLog=web_log_file)
5.1.1 改进案例一:通过re正则模块获取IP地址
import re
def webUVByRegex():
web_log_file = r"D:\project0218\fileIO\access_log"
ip_address = r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
# 从文件中获取客户端地址
ip_list = []
with open(web_log_file, mode="r") as fobj:
for line in fobj:
# 类似于grep,能过滤到数据返回Match Object, 否则返回None
result = re.search(ip_address, line)
if result:
ip_list.append(result.group())
# IP去重,统计次数
for ip in set(ip_list):
print("客户端地址: %s, 访问次数: %s" % (ip, ip_list.count(ip)))
5.2 案例二:获取目录下文件名
import os
# 递归获取目录下所有文件名
def getFileName(directory):
file_list = []
for dir_name, sub_dir_list, file_name_list in os.walk(directory):
# 判断对应的目录下有文件
if len(file_name_list) > 0:
for f_name in file_name_list:
full_file_name = dir_name + "\\" + f_name
file_list.append(full_file_name)
return file_list
if __name__ == '__main__':
file_list = getFileName(r"E:\project0528\北京")
print(file_list)
5.3 案例三: 文件批量重命名
# 批量文件重命名
def fileRename():
file_list = getFileName(r"E:\project0528\北京")
for old_file in file_list:
# 判断.txt结尾的文件
if old_file.endswith(".txt"):
new_file_name = old_file.replace("txt", "sql")
os.rename(old_file, new_file_name)
5.4 案例四: 文件MD5校验
# 文件MD5校验
def fileMD5(filename):
md5_tool = hashlib.md5()
with open(filename, mode="rb") as fobj:
# 循环读取文件内容
while True:
data = fobj.read(4096)
if data:
md5_tool.update(data)
else:
break
return md5_tool.hexdigest()
if __name__ == '__main__':
a = fileMD5(filename=r"E:\project0528\utils\access_log")
b = fileMD5(filename=r"E:\project0528\utils\test1.txt")
if a == b:
print("数据一致")
else:
print("数据不一致")
5.5 案例五:对比目录间文件差异
# 检测目录间文件差异
def fileDiff():
source_directory = r"E:\project0528\北京"
src_file_list = getFileName(source_directory)
for src_file in src_file_list:
# 获取备份目录下的同名的文件
dest_file = src_file.replace("北京", "backup")
# 同名的目的文件不存在
if not os.path.exists(dest_file):
print("文件【%s】丢失!!!!!!!!" % src_file)
else:
# 判断文件内容不一致
src_file_md5 = fileMD5(src_file)
dest_file_md5 = fileMD5(dest_file)
if dest_file_md5 != src_file_md5:
print("源文件【%s】--------目的文件【%s】------数据不一致!!!!" % (src_file, dest_file))
if __name__ == '__main__':
fileDiff()
5.6 案例六:实现文件完全备份、增量备份
# 完全备份, 增量备份
import tarfile
from utils import fileManager as fm
import datetime
import pickle
# 完全备份
def fullBackUP():
source_directory = r"E:\project0528\北京"
# 创建完全备份压缩包
tar_file = r"E:\project0528\backup\data_%s.tar.gz" % datetime.datetime.now().strftime("%Y_%m_%d_%H_%M_%S")
tar_obj = tarfile.open(tar_file, mode="w:gz")
# {"文件名称":"文件MD5"} ,便于后续的增量备份
file_md5_dict = {}
# 获取源目录下的所有文件, 添加到压缩包
src_file_list = fm.getFileName(source_directory)
for src_file in src_file_list:
tar_obj.add(src_file)
# 对文件进行MD5校验,写入字典
src_file_md5 = fm.fileMD5(src_file)
file_md5_dict[src_file] = src_file_md5
tar_obj.close()
# 将字典持久化保存
md5_file = r"E:\project0528\backup\md5.file"
with open(md5_file, mode="wb") as fobj:
pickle.dump(file_md5_dict, fobj)
# 增量备份
def increBackUP():
source_directory = r"E:\project0528\北京"
# 创建增量备份压缩包
tar_file = r"E:\project0528\backup\data_incre_%s.tar.gz" % datetime.datetime.now().strftime("%Y_%m_%d_%H_%M_%S")
tar_obj = tarfile.open(tar_file, mode="w:gz")
# 获取完全备份时生成的字典
md5_file = r"E:\project0528\backup\md5.file"
with open(md5_file, mode="rb") as fobj:
file_md5_dict = pickle.load(fobj)
# 重新遍历源目录下的文件,检测变化
src_file_list = fm.getFileName(source_directory)
for src_file in src_file_list:
# 检测新文件
if src_file not in file_md5_dict.keys():
tar_obj.add(src_file)
# 对新文件进行校验,更新字典
file_new_md5 = fm.fileMD5(src_file)
file_md5_dict[src_file] = file_new_md5
else:
# 检测文件内容有变化
file_old_md5 = file_md5_dict.get(src_file)
file_new_md5 = fm.fileMD5(src_file)
if file_new_md5 != file_old_md5:
tar_obj.add(src_file)
# 更新旧文件的校验码
file_md5_dict[src_file] = file_new_md5
# 更新硬盘中的字典文件
with open(md5_file, mode="wb") as fobj:
pickle.dump(file_md5_dict, fobj)
if __name__ == '__main__':
day_of_week = datetime.datetime.now().strftime("%w")
if day_of_week == "1":
fullBackUP()
else:
increBackUP()
5.7 案例七:多线程检测网段在线主机
import subprocess
def checkPing(ip):
ping_cmd = "ping -n 1 -w 1 %s" % ip
null_obj = open("win_null_file", mode="wb")
ping_result = subprocess.call(ping_cmd, shell=True, stdout=null_obj, stderr=null_obj)
if ping_result == 0:
print("主机%s在线!!!!" % ip)
if __name__ == '__main__':
for i in range(1, 255):
host_ip = "192.168.102.%s" % i
checkPing(ip=host_ip)
5.8 改进案例七:多线程检测网段在线主机
import subprocess
import threading
def checkPing(ip):
null_file = open("null_file", mode="wb")
ping_cmd = "ping -n 1 -w 1 %s" % ip
ping_result = subprocess.call(ping_cmd, shell=True, stdout=null_file, stderr=null_file)
if ping_result == 0:
print("主机%s在线!!" % ip)
null_file.close()
if __name__ == '__main__':
for i in range(1,254):
ip = "192.168.3.%s" % i
ping_thread = threading.Thread(target=checkPing, args=(ip,))
ping_thread.start()