五、文件的概念

文件操作作用:Linux操作系统中一切皆文件!

1、什么是文件

内存中存放的数据在计算机关机后就会消失。要长久保存数据,就要使用硬盘、光盘、U 盘等设备。为了便于数据的管理和检索,引入了“文件”的概念。

一篇文章、一段视频、一个可执行程序,都可以被保存为一个文件,并赋予一个文件名。操作系统以文件为单位管理磁盘中的数据。一般来说,文件可分为文本文件、视频文件、音频文件、图像文件、可执行文件等多种类别。

img

2、文件操作内容?

在日常操作中,我们对文件的主要操作:创建文件、打开文件、文件读写、文件备份等等

img

3、文件操作的作用

文件操作的作用就是把一些内容(数据)存储存放起来,可以让程序下一次执行的时候直接使用,而不必重新制作一份,省时省力。

简单来说:文件的作用就是为了实现数据的持久化存储!

4、文件操作应用场景

Nginx日志文件读取

保存分析结果到文件

六、文件的基本操作

1、文件操作三步走

① 打开文件

② 读写文件

③ 关闭文件

2、open函数打开文件

在Python,使用open()函数,可以打开一个已经存在的文件,或者创建一个新文件,语法如下:

1
2
f = open(name, mode)
注:返回的结果是一个file文件对象(后续会学习,只需要记住,后续方法都是f.方法())

name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径)。

mode:设置打开文件的模式(访问模式):只读r、写入w、追加a等。

r模式:代表以只读模式打开一个已存在的文件,后续我们对这个文件只能进行读取操作。如果文件不存在,则直接报错。另外,r模式在打开文件时,会将光标放在文件的第一行(开始位置)。

w模式:代表以只写模式打开一个文件,文件不存在,则自动创建该文件。w模式主要是针对文件写入而定义的模式。但是,要特别注意,w模式在写入时,光标也是置于第一行同时还会清空原有文件内容。

a模式:代表以追加模式打开一个文件,文件不存在,则自动创建该文件。a模式主要也是针对文件写入而定义模式。但是和w模式有所不同,a模式不会清空文件的原有内容,而是在文件的尾部追加内容。

文件路径:① 绝对路径 ② 相对路径

① 绝对路径:绝对路径表示绝对概念,一般都是从盘符开始,然后一级一级向下查找(不能越级),直到找到我们要访问的文件即可。

比如访问C盘路径下的Python文件夹下面的python.txt文件,其完整路径:

1
2
3
4
Windows
C:\Python\python.txt
Linux
/usr/local/nginx/conf/nginx.conf

绝对路径一般路径固定了,文件就不能进行移动,另外在迁移过程中会比较麻烦。

② 相对路径:相对路径表示相对概念,不需要从盘符开始,首先需要找到一个参考点(就是Python文件本身)

同级关系:我们要访问的文件与Python代码处于同一个目录,平行关系,同级关系的访问可以使用./文件名称或者直接写文件名称即可

上级关系:如果我们要访问的文件在当前Python代码的上一级目录,则我们可以通过../来访问上一级路径(如果是多级,也可以通过../../../去一层一层向上访问

下级关系:如果我们要访问的文件在与Python代码同级的某个文件夹中,则我们可以通过文件夹名称/来访问某个目录下的文件

3、write函数写入文件

基本语法:

1
f.write('要写入的内容,要求是一个字符串类型的数据')

4、close函数关闭文件

1
f.close()

5、文件操作入门案例

1
2
3
4
5
6
# 1、打开文件
f = open('python.txt', 'w')
# 2、写入内容
f.write('人生苦短,我学Python!')
# 3、关闭文件
f.close()

强调一下:中文乱码问题,默认情况下,计算机常用编码ASCII、GBK、UTF-8

6、解决写入中文乱码问题

1
2
3
4
5
6
# 1、打开文件
f = open('python.txt', 'w', encoding='utf-8')
# 2、写入内容
f.write('人生苦短,我学Python!')
# 3、关闭文件
f.close()

7、文件的读取操作

read(size)``方法:主要用于文本类型或者二进制文件(图片、音频、视频…)数据的读取

size表示要从文件中读取的数据的长度(单位是字符/字节),如果没有传入size,那么就表示读取文件中所有的数据

read(size):size按字节读,还是按照字符长度读取,和open()中的第二个参数,访问模式mode有关。

r以文本方式读取文件:按字符长度读取

rb以二进制方式读取文件:比如读取图片、音频(3MB = 3 * 1024 * 1024字节)、视频,按字节大小读取,英文状态下,1个字节 = 1个字符(如a、b、c、1、2、3)

1
2
3
4
5
6
7
8
9
f.read()  # 读取文件的所有内容
f.read(1024) # 读取1024个字符长度文件内容,字母或数字
# 1、打开文件
f = open('python.txt', 'r', encoding='utf-8')
# 2、使用read()方法读取文件所有内容
contents = f.read()
print(contents)
# 3、关闭文件
f.close()

适合场景:既可以读取小文件(一次性全部读取过来),也适合中大型文件读取(分长度或者字段,一点一点进行读取)。

readlines()``方法:主要用于文本类型数据的读取

readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素。

适合小文件一次性读取

1
2
3
4
5
6
7
8
# 1、打开文件
f = open('python.txt', 'r', encoding='utf-8')
# 2、读取文件
lines = f.readlines()
for line in lines:
print(line, end='')
# 3、关闭文件
f.close()

readline()``方法:一次读取一行内容,每运行一次readline()函数,其就会将文件的指针向下移动一行

readline():没有s,代表一次读取文件的一行,适合大文件读取

1
2
3
4
5
6
7
8
9
10
11
12
13
f = open('python.txt’)

while True:
# 读取一行内容
content = f.readline()
# 判断是否读取到内容
if not content:
break
# 如果读取到内容,则输出
print(content)

# 关闭文件
f.close()

小结:

read(size) :适合大文件读取,read(size)适合大文件读取,read()适合小文件读取

readlines() :适合小文件读取

readline() :适合大文件读取

8、扩展: with上下文管理器 与 for line in f文件对象

为什么要使用with上下文管理器?答:文件操作完成后必须要手工关闭文件,而with上下文管理器会在操作结束后,自动关闭之前已经打开的文件对象,不需要手工操作。

with上下文管理器基本语法:

1
2
with open('data.txt', 'r', encoding='utf-8') as f:
xxx

for line in f文件对象作用?文件需要通过read/readline/readlines,但是操作都比较麻烦,python3.8以后版本提供一个新操作方式:

1
2
for line in f文件对象:
print(line)

七、文件和文件夹操作

作用:针对文件或文件夹进行相关操作,如删除文件、重命名文件、创建目录、移除目录等等

1、os模块

在Python中文件和文件夹的操作要借助os模块里面的相关功能,具体步骤如下:

第一步:导入os模块

1
import os

第二步:调用os模块中的相关方法

1
os.函数名()

2、与文件操作相关方法

编号 函数 功能
1 os.rename(旧文件名称,新文件名称) 对文件进行重命名操作
2 os.remove(要删除文件名称) 对文件进行删除操作

案例:把Python项目目录下的python.txt文件,更名为linux.txt,休眠20s,刷新后,查看效果,然后对这个文件进行删除操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 第一步:导入os模块
import os
# 第三步:引入time模块
import time


# 第二步:使用os.rename方法对python.txt进行重命名
os.rename('python.txt', 'linux.txt')

# 第四步:休眠20s
time.sleep(20)

# 第五步:删除文件(linux.txt)
os.remove('linux.txt')

小结:

文件与文件夹操作,必须导入(os)模块?

重命名:os.rename()

删除文件:os.remove()

3、与文件夹操作相关方法

前提:

1
import os

相关方法:

编号 函数 功能
1 os.mkdir(新文件夹名称) 创建一个指定名称的文件夹
2 os.getcwd() current work directory,获取当前所在目录名称(在哪里)
3 os.chdir(切换后目录名称) change directory,切换目录
4 os.listdir(目标目录) 获取指定目录下的文件信息,返回列表
5 os.rmdir(目标目录) 用于删除一个指定名称的”空”文件夹

案例1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 导入os模块
import os


# 1、使用mkdir方法创建一个images文件夹
if not os.path.exists('images'):
os.mkdir('images')

if not os.path.exists('images/avatar')
os.mkdir('images/avatar')

# 2、getcwd = get current work directory
print(os.getcwd())

# 3、os.chdir,ch = change dir = directory切换目录
os.chdir('images/avatar')
print(os.getcwd())

# 切换到上一级目录 => images
os.chdir('../../')
print(os.getcwd())

# 4、使用os.listdir打印当前所在目录下的所有文件,返回列表
print(os.listdir())

# 5、删除空目录
os.rmdir('images/avatar')

案例2:准备一个static文件夹以及file1.txt、file2.txt、file3.txt三个文件

① 在程序中,将当前目录切换到static文件夹

② 创建一个新images文件夹以及test文件夹

③ 获取目录下的所有文件

④ 移除test文件夹

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 导入os模块
import os

# ① 在程序中,将当前目录切换到static文件夹
os.chdir('File')
# print(os.getcwd())

# ② 创建一个新images文件夹以及test文件夹
if not os.path.exists('images'):
os.mkdir('images')

if not os.path.exists('test'):
os.mkdir('test')

# ③ 获取目录下的所有文件
# print(os.listdir())
for file in os.listdir():
print(file)

# ④ 移除test文件夹
os.rmdir('test')

小结:

编号 函数 功能
1 os.mkdir(新文件夹名称) 创建目录
2 os.getcwd() 获取当前工作路径
3 os.chdir(切换后目录名称) 切换目录
4 os.listdir(目标目录) 获取目录下的所有文件
5 os.rmdir(目标目录) 删除空目录

4、shutil模块实现递归删除

作用:用于删除非空目录

1
2
3
4
5
# 导入shutil模块
import shutil

# 递归删除非空目录
shutil.rmtree('要删除文件夹路径')

递归删除文件夹的原理:理论上,其在删除过程中,如果文件夹非空,则自动切换到文件夹的内部,然后把其内部的文件,一个一个删除,当所有文件删除完毕后,返回到上一级目录,删除文件夹本身。

延伸面试题:你熟悉Python运维开发,介绍一下你以前使用过哪些模块?模块大致功能?

答:os系统模块:进程管理、文件操作;random随机数模块:生成一些随机数;shutil模块,递归删除目录;time模块,获取系统时间,休眠等操作 => 将来还可以把运维相关模块融合进来。

八、Nginx日志文件分析统计

1、场景说明

Nginx日志:error.log(错误日志)、access.log(访问日志)

在企业级应用中,Nginx日志是系统运行情况的重要数据来源,记录了用户访问的详细信息,包括IP地址、访问路径、状态码等。企业需要定期分析这些日志,以了解访问来源、使用模式、异常状态(如404或500)及潜在的安全威胁(如频繁访问的恶意IP)。

开发一个Python自动化脚本,读取Nginx日志文件,提取关键信息并生成统计报告,以便用于以下场景:

  • 访问分析:统计各IP地址的访问次数,发现高频访问的用户或潜在攻击者。
  • 异常检测:统计HTTP状态码分布,发现404错误(资源缺失)或500错误(服务器异常)。
  • 性能优化:通过日志数据,分析系统访问负载,为后续性能调优提供依据。

普及响应状态码(HTTP请求,响应时都会返回一个状态码,本质就是一个数字,代表响应状态;如200代表正常响应,404代表资源缺失-文件未找到,500代表服务器端异常-可能代码有问题)

2、任务拆解

日志数据解析:读取Nginx日志文件并提取关键信息(IP地址、状态码)。

数据统计:统计每个IP地址的访问次数和每种状态码的出现频率。

结果输出:将统计结果保存到文件并输出到控制台。

3、任务实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 初始化统计变量
ip_stats = {}
status_stats = {}

# 读取nginx_access.log文件并解析内容
with open("nginx_access.log", "r") as file:
for line in file:
parts = line.split()
ip = parts[0] # 提取IP地址
status = parts[8] # 提取状态码

# 统计IP地址出现次数
if ip not in ip_stats:
ip_stats[ip] = 1
else:
ip_stats[ip] += 1

# 统计状态码出现次数
if status not in status_stats:
status_stats[status] = 1
else:
status_stats[status] += 1

# 将统计结果写入本地文件
with open("nginx_summary.txt", "w") as summary:
summary.write("IP地址统计:\n")
for ip, count in ip_stats.items():
summary.write(f"{ip}: {count} 次\n")

summary.write("\n状态码统计:\n")
for status, count in status_stats.items():
summary.write(f"{status}: {count} 次\n")

# 打印结果作为输出
print("IP地址统计:")
for ip, count in ip_stats.items():
print(f"{ip}: {count} 次")

print("\n状态码统计:")
for status, count in status_stats.items():
print(f"{status}: {count} 次")