iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Python使用os模块实现更高效地读写文件
  • 788
分享到

Python使用os模块实现更高效地读写文件

2024-04-02 19:04:59 788人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

目录使用 os.open 打开文件使用 os.read 读取文件使用 os.write 写入文件使用 os.open 打开文件 无论是读文件还是写文件,都要先打开

使用 os.open 打开文件

无论是读文件还是写文件,都要先打开文件。说到打开文件,估计首先想到的就是内置函数 open(即 io.open),那么它和 os.open 有什么关系呢?

内置函数 open 实际上是对 os.open 的封装,在 os.open 基础上增加了相关访问方法。因此为了操作方便,应该调用内置函数 open 进行文件操作,但如果对效率要求较高的话,则可以考虑使用 os.open。

此外 open 函数返回的是一个文件对象,我们可以在此基础上进行任意操作;而 os.open 返回的是一个文件描述符,说白了就是一个整数,因为每一个文件对象都会对应一个文件描述符。

import os

f1 = open("main.c", "r")
f2 = os.open("main.c", os.O_RDONLY)

print(f1.__class__)
print(f2.__class__)
"""
<class '_io.TextIOWrapper'>
<class 'int'>
"""

python 的 open 函数实际上是封装了 C 的 fopen,C 的 fopen 又封装了系统调用提供的 open。

操作系统提供了很多的系统调用,打开文件则是 open,我们看到它返回一个整数,这个整数就是对应的文件描述符。C 的 fopen 封装了系统调用的 open,返回的是一个文件指针。

所以内置函数 open 和 os.open 的区别就更加清晰了,内置函数 open 在底层会使用 C 的 fopen,得到的是一个封装好的文件对象,在此基础上可以直接操作。至于 os.open 在底层则不走 C 的 fopen,而是直接使用系统调用提供的 open,得到的是文件描述符。

os 模块内部的函数基本上都是直接走的系统调用,所以模块名才叫 os。

然后我们使用 os.open 一般需要传递两个参数,第一个参数是文件名,第二个参数是模式,举个栗子:

import os

# 以只读方式打开,要求文件必须存在
# 打开时光标处于文件的起始位置
os.open("main.c", os.O_RDONLY)

# 以只写方式打开,要求文件必须存在
# 打开时光标处于文件的起始位置
os.open("main.c", os.O_WRONLY)

# 以可读可写方式打开,要求文件必须存在
# 打开时光标处于文件的起始位置
os.open("main.c", os.O_RDWR)

# 以只读方式打开,文件不存在则创建
# 存在则不做任何事情,等价于 os.O_RDONLY
# 打开时光标处于文件的起始位置
os.open("main.c", os.O_RDONLY | os.O_CREAT)

# 同理 os.O_WRONLY 和 os.O_RDWR 与之类似
os.open("main.c", os.O_WRONLY | os.O_CREAT)
os.open("main.c", os.O_RDWR | os.O_CREAT)

# 文件不存在时创建,存在时清空
# 打开时光标处于文件的起始位置
os.open("main.c",
        os.O_WRONLY | os.O_CREAT | os.O_TRUNC)
# 当然读取文件也是可以的
# 比如 os.O_RDONLY | os.O_CREAT | os.O_TRUNC
# 也是文件存在时清空内容,但是这没有任何意义
# 因为读取的时候将文件清空了,那还读什么?

# 文件不存在时创建,存在时追加
# 打开时光标处于文件的末尾
os.open("main.c",
        os.O_WRONLY | os.O_CREAT | os.O_APPEND)

# 所以
"""
open里面的读模式等价于这里的 os.O_RDONLY
open里面的写模式等价于这里的 os.O_WRONLY | os.O_CREATE | os.O_TRUNC
open里面的追加模式等价于这里的 os.O_WRONLY | os.O_CREATE | os.O_APPEND
"""

好,打开方式介绍完了,那么怎么读取和写入呢?很简单,读取使用 os.read,写入使用 os.write。

使用 os.read 读取文件

先来看读取,os.read 接收两个参数,第一个参数是文件描述符,第二个参数是要读取多少个字节。

import os

fd = os.open("main.c", os.O_RDONLY)
# 使用 os.read 进行读取
# 这里读取 20 个字节
data = os.read(fd, 20)
print(data)
"""
b'#include <Python.h>'
"""

# 再读取 20 个字节
data = os.read(fd, 20)
print(data)
"""
b'\n#include <ctype.h>'
"""

# 继续读取
data = os.read(fd, 20)
# 由于只剩下一个字节
# 所以就读取了一个字节
# 显然此时文件已经读完了
print(data)
"""
b'\n'
"""

# 文件读取完毕之后
# 再读取的话会返回空字节串
print(os.read(fd, 20))  # b''
print(os.read(fd, 20))  # b''
print(os.read(fd, 20))  # b''

所以这就是文件的读取方式,还是很简单的。然后在读取的过程中,我们还可以移动光标,通过 os.lseek 函数。

  • os.lseek(fd, m, 0):将光标从文件的起始位置向后移动 m 个字节;
  • os.lseek(fd, m, 1):将光标从当前所在的位置向后移动 m 个字节;
  • os.lseek(fd, m, 2):将光标从文件的结束位置向后移动 m 个字节;

如果 m 大于 0,表示向后移动,m 小于 0,表示向前移动。所以当第三个参数为 2 的时候,也就是结束位置,那么 m 一般为负数。因为相对于结束位置,肯定要向前移动,当然向后移动也可以,不过没啥意义;同理当第三个参数为 0 时,m 一般为正数,相对于起始位置,肯定要向后移动。

import os

fd = os.open("main.c", os.O_RDONLY)
data = os.read(fd, 20)
print(data)
"""
b'#include <Python.h>'
"""

# 从文件的起始位置向后移动 0 个字节
# 相当于将光标设置在文件的起始位置
os.lseek(fd, 0, 0)
data = os.read(fd, 20)
print(data)
"""
b'#include <Python.h>'
"""

# 设置在结束位置
os.lseek(fd, 0, 2)
print(os.read(fd, 20))  # b''

# 此时就什么也读不出来了

然后我们提一下 stdin, stdout, stderr,含义应该不需要解释了,重点是它们对应的文件描述符分别为 0, 1, 2。

import os

# 从标准输入里面读取 10 个字节
# 没错,此时作用类似于 input
while True:
    data = os.read(0, 10).strip()
    print(f"你输入了:", data)
    if data == b"exit":
        break

我们测试一下:

os.read 可以实现 input 的效果,并且效率更高。另外当按下回车时,换行符也会被读进去,所以需要 strip 一下。然后我们这里读的是 10 个字节,如果一次读不完,那么会分多次读取。在读取文件的时候,也是同理。

from io import BytesIO
import os

fd = os.open("main.c", os.O_RDONLY)
buf = BytesIO()

while True:
    data = os.read(fd, 10)
    if data != b"":
        buf.write(data)
    else:
        break
print(buf.getvalue().decode("utf-8"))
"""
#include <Python.h>
#include <ctype.h>

"""

然后 os.read 还可以和内置函数 open 结合,举个栗子:

import os
import io

f = open("main.c", "r")
# 通过 f.fileno() 即可拿到对应的文件描述符
# 虽然这里是以文本模式打开的文件
# 但只要拿到文件描述符,都可以交给 os.read
print(
    os.read(f.fileno(), 10)
)  # b'#include <'

# 查看光标位置
print(f.tell())  # 10

# 移动光标位置
# 从文件开头向后移动 5 字节
f.seek(5, 0)
print(f.tell())  # 5
# os.lseek 也可以实现
os.lseek(f.fileno(), 3, 0)
print(f.tell())  # 3
# 此时会从第 4 个字节开始读取
print(f.read())
"""
clude <Python.h>
#include <ctype.h>

"""

# os.lseek 比 f.seek 要强大一些
# 移动到文件末尾,此时没问题
f.seek(0, 2)
print(f.tell())  # 41

try:
    f.seek(-1, 2)
except io.UnsupportedOperation as e:
    print(e)
"""
can't do nonzero end-relative seeks
"""
# 但如果要相对文件末尾移动具体的字节数
# 那么 f.seek 不支持,而 os.lseek 是可以的
print(f.tell())  # 41
os.lseek(f.fileno(), -1, 2)
print(f.tell())  # 40
# 最后只剩下一个换行符
print(os.read(f.fileno(), 10))  # b'\n'

是不是很好玩呢?

使用 os.write 写入文件

然后是写入文件,调用 os.write 即可写入。

import os

# 此时可读可写,文件不存在时自动创建,存在则清空
fd = os.open("1.txt", os.O_RDWR | os.O_CREAT | os.O_TRUNC)
# 写入内容,接收两个参数
# 参数一:文件描述符;参数二:bytes 对象
os.write(fd, b"hello, ")
os.write(fd, "古明地觉".encode("utf-8"))
# 读取内容
data = os.read(fd, 1024)
print(data)  # b''
# 问题来了,为啥读取不到内容呢?
# 很简单,因为光标会伴随着数据的写入而不断后移
# 这样的话,数据才能不断地写入
# 因此,现在的光标位于文件的结尾处
# 想要查看写入的内容需要移动到开头
os.lseek(fd, 0, 0)
print(os.read(fd, 1024).decode("utf-8"))
"""
hello, 古明地觉
"""
# 从后往前移动 3 字节
os.lseek(fd, -3, 2)
print(os.read(fd, 1024).decode("utf-8"))
"""
觉
"""

以上就是文件的写入,当然它也可以和内置函数 open 结合,通过 os.write(f.fileno(), b"xxx") 进行写入。但是不建议 os.open 和 open 混用,其实工作中使用 open 就足够了。

然后是 stdout 和 stderr,和 os.write 结合可以实现 print 的效果。

import os

os.write(1, "往 stdout 里面写入\n".encode("utf-8"))
os.write(2, "往 stderr 里面写入\n".encode("utf-8"))

执行一下,查看控制台:

以上就是 os.write 的用法。

最后是关闭文件,使用 os.close 即可。

import os
import io

fd = os.open("1.txt", os.O_RDWR | os.O_CREAT | os.O_TRUNC)
# 关闭文件
os.close(fd)

# 文件对象也是可以的
f = open(r"1.txt", "r")
os.close(f.fileno())
try:
    f.read()
except OSError as e:
    print(e)
"""
[Errno 9] Bad file descriptor
"""

如果是调用 f.close() 关闭文件,再进行读取的话,会抛出一个 ValueError,提示 I/O operation on closed file。这个报错信息比较明显,不应该在关闭的文件上执行 IO 操作,因为文件对象知道文件已经关闭了,毕竟调用的是自己的 close 方法,所以这个报错是解释器给出的。当然啦,调用 f.close 也会触发 os.close,因为关闭文件最终还是要交给操作系统负责的。

但如果是直接关闭底层的文件描述符,文件对象是不知道的,再使用 f.read() 依旧会触发系统调用,也就是 os.read。而操作系统发现文件已经关闭了,所以会报错:文件描述符有问题,此时就是一个 OSError,报错信息是操作系统给出的。

import os

f = open(r"1.txt", "r")
# 文件是否关闭
print(f.closed)  # False
os.close(f.fileno())
print(f.closed)  # False

# 所以调用 os.close,文件对象 f 并不知道
# f.read 依旧会触发系统调用

如果是使用 f.close()。

f = open(r"1.txt", "r")
f.close()
print(f.closed)  # True

后续执行 IO 操作,就不会再走系统调用了,而是直接抛出 ValueError,原因是文件对象知道文件已经关闭了。

除了 os.close 之外,还有一个 os.closerange,可以关闭多个文件描述符对应的文件。

import os

# 关闭文件描述符为 1、2、3、4 的文件 
os.closerange(1, 5)

该方法不是很常用,了解一下即可。

以上就是使用 os 模块操作文件,它是直接使用操作系统提供的系统调用,所以效率上会比内置函数 open 要高一些。但是工作中还是不太建议使用 os 模块操作文件,使用内置函数 open 就好。

到此这篇关于Python使用os模块实现更高效地读写文件的文章就介绍到这了,更多相关Python os模块读写文件内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Python使用os模块实现更高效地读写文件

本文链接: https://www.lsjlt.com/news/119484.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Python使用os模块实现更高效地读写文件
    目录使用 os.open 打开文件使用 os.read 读取文件使用 os.write 写入文件使用 os.open 打开文件 无论是读文件还是写文件,都要先打开...
    99+
    2024-04-02
  • Python文件处理方法、os模块和glob模块怎么使用
    这篇“Python文件处理方法、os模块和glob模块怎么使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Python文件...
    99+
    2023-06-30
  • Python文件处理方法、os模块和glob模块如何使用
    这篇文章主要讲解了“Python文件处理方法、os模块和glob模块如何使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python文件处理方法、os模块和glob模块如何使用”吧!一、文...
    99+
    2023-07-06
  • python内置模块OS 实现SHELL端文件处理器
    目录OS 模块带path判断文件判断文件夹判断文件是否存在获取文件大小获取路径及文件获取绝对路径返回文件名获取文件路径路径拼接不带path获取平台获取所有文件当前工作路径目录操作重命...
    99+
    2024-04-02
  • 怎么在python中用os模块实现批量移动文件
    这篇“怎么在python中用os模块实现批量移动文件”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么在python中用os...
    99+
    2023-06-30
  • 如何在python中用os模块实现批量移动文件
    本文介绍一下利用python批量把一个文件夹(及其子文件夹)下面的特定类型的文件移动到另一个文件夹下 通过python操作系统目录及其文件,需要用到os包,本次具体用到如下方法 os...
    99+
    2024-04-02
  • 如何用 Java 实现高效的文件读写操作
    1. 使用缓冲流 缓冲流是一种可以将数据临时存储在缓冲区中的流。当需要读写数据时,它会先将数据读入或写入缓冲区,然后再从缓冲区读出或写入文件。这样可以减少对文件的读写次数,从而提高文件读写效率。 import java.io.*; p...
    99+
    2024-02-26
    Java 文件读写 性能优化
  • Python递归文件中os模块的实际应用方式
    本篇内容主要讲解“Python递归文件中os模块的实际应用方式”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Python递归文件中os模块的实际应用方式”吧!os模块在实际的操作中应用非常广泛,...
    99+
    2023-06-17
  • 如何在PHP中实现高效的文件读写操作?
    PHP 是一种广泛使用的编程语言,它在网站开发中扮演着重要的角色。在 PHP 中,文件读写操作是经常使用的功能之一,它可以帮助我们读取和写入文件,以便存储和处理数据。然而,文件读写操作可能会降低代码的性能,因此我们需要采取一些措施来提高 P...
    99+
    2023-08-27
    大数据 编程算法 文件
  • 利用python实现ftp的文件读写
    ftp登陆连接 from ftplib import FTP #加载ftp模块 ftp=FTP() #设置变量 ftp.set_debuglevel(2) ...
    99+
    2023-01-31
    文件 python ftp
  • 如何在Go中实现高效的文件读写操作?
    Go是一门高效、并发、简洁的编程语言,常被用于处理大规模数据和高并发的网络应用。在Go中,文件读写是一项非常常见的操作,而如何实现高效的文件读写操作是一个值得深入研究的话题。 在本文中,我们将介绍一些在Go中实现高效文件读写操作的技巧和最...
    99+
    2023-09-05
    缓存 日志 文件
  • 如何使用h5+js实现本地文件读取和写入
    小编给大家分享一下如何使用h5+js实现本地文件读取和写入,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!   代码如下:   读取本地文件   <!doctypehtml>...
    99+
    2024-04-02
  • python使用tkinter模块实现文件选择功能
    目录前言1.导入库和模块2.编写按钮命令3. 窗体初始化及布局4.运行前言 学习Python中,总想做个图形界面,找来找去,找到了tkinter。 练习内容:图形界面中,点击按钮后,...
    99+
    2024-04-02
  • 使用python怎么实现一个文件读写函数
    本篇文章给大家分享的是有关使用python怎么实现一个文件读写函数,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。用到xlrd库函数需要预先install命令:pip insta...
    99+
    2023-06-06
  • Python 程序设计入门(025)—— 使用 os 模块操作文件与目录
    Python 程序设计入门(025)—— 使用 os 模块操作文件与目录 目录 Python 程序设计入门(025)—— 使用 os 模块操作文件与目录一、操作目录的常用函数1、os 模块提供...
    99+
    2023-08-31
    python
  • PHP开发中如何使用Memcache实现高效的数据读写和更新?
    PHP开发中如何使用Memcache实现高效的数据读写和更新?Memcache是一种内存缓存技术,可以提供高速的数据访问和存储。在PHP开发中,如果能够合理地使用Memcache,就可以大大提高数据的读取和更新效率。本文将介绍如何使用Mem...
    99+
    2023-11-07
    Memcache PHP开发 高效数据读写更新
  • 如何在PHP和NumPy中实现高效的异步文件读写?
    文件读写是Web应用程序中常见的任务之一。而在高并发场景下,同步的文件读写会阻塞进程,影响系统的性能表现。因此,异步文件读写成为提高Web应用程序性能的重要手段。 本文将介绍如何在PHP和NumPy中实现高效的异步文件读写,以提高Web应...
    99+
    2023-10-05
    numpy 异步编程 文件
  • Go语言文件API:如何利用并发编程实现高效读写?
    在Go语言中,文件操作是非常常见的操作。然而,在进行文件读写时,如何提高效率是一个非常重要的问题。本文将介绍如何利用Go语言的并发编程技术来实现高效的文件读写操作。 Go语言的文件API 在Go语言中,我们可以使用os包中提供的文件API...
    99+
    2023-11-02
    并发 文件 api
  • 如何在 Python 中使用 path 模块,让你的代码更加高效?
    Python是一门强大的编程语言,它提供了许多内置模块和库,使得开发者可以更加高效地编写程序。其中,path模块是一个非常实用的模块,它可以帮助我们操作文件路径和目录,让我们的代码更加高效。本文将介绍如何在Python中使用path模块,以...
    99+
    2023-08-08
    教程 面试 path
  • 完全指南:使用pip自定义源安装Python模块,助你更高效地管理Python环境
    专业指导:深入解析pip如何指定源安装,帮你更好地管理Python环境,需要具体代码示例 引言:Python作为一门广泛应用的编程语言,拥有强大的生态系统,其中pip作为其包管理工具,为开发者提供了便捷的第三方库安装和管理机制。...
    99+
    2024-01-18
    pip指定源
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作