百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

Python文件操作的实用编程技巧总结,建议收藏学习

off999 2024-09-27 13:57 30 浏览 0 评论

这个问题看似简单,但是由于py2 和 py3 的巨大差异导致我们依然要深入研究一下。

那么 python2 和 python3 的什么区别导致了这种差异的发生呢?

有需要Python学习资料的小伙伴吗?小编整理【一套Python资料、源码和PDF】,感兴趣者可以关注小编后私信学习资料(是关注后私信哦)反正闲着也是闲着呢,不如学点东西啦

答:python2 和 python3 之间字符串的语意发生了变化

python2 有两种字符串的类型:

(1)str

表面上看是字符串,但是实际上是抽象的一串连续的字节(字符串中每个字符都是一个字节)

(2)unicode

这个类型是在更多不同的语言加入以后不得不进行调整的,不再用一个字节表示一个字符,但是,我们进行文件操作的时候是不支持直接将多个字节一下子存储进去的,我们必须将其转化成某种单个字节的编码再进行存储操作

示例代码:

将文字编码:

In [1]: a = u'你好世界'
In [2]: a.encode('utf8')
Out[2]: '\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xb8\x96\xe7\x95\x8c'
In [3]: a.encode('gbk')
Out[3]: '\xc4\xe3\xba\xc3\xca\xc0\xbd\xe7'

可以看到 utf-8 使用的字节比Gbk多

将文字解码:

注意:这里编码和解码一定要对应,否则会出现乱码。

代码示例:

In [5]: '\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xb8\x96\xe7\x95\x8c'.decode('gbk')
Out[5]: u'\u6d63\u72b2\u30bd\u6d93\u682b\u666b'
In [6]: print u'\u6d63\u72b2\u30bd\u6d93\u682b\u666b'
浣犲ソ涓栫晫

代码示例:

In [8]: '\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xb8\x96\xe7\x95\x8c'.decode('utf8')
Out[8]: u'\u4f60\u597d\u4e16\u754c'
In [9]: print u'\u4f60\u597d\u4e16\u754c'
你好世界

1.python2 的文本读写

文本就是Unicode 字符串,我们写入文件前先要对其选择一个方式进行编码,我们读取文件的时候也要对其进行先解码,将其换原成 unicode 。

文本的写入:

f = open('test.txt','w')
s = u'你好世界'
f.write(s.encode('utf8'))

文本的读出:

In [8]: f = open('test.txt','r')
In [9]: t = f.read()
In [10]: t
Out[10]: '\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xb8\x96\xe7\x95\x8c'

可以看到这样读出来的都是字节码

我们必须要进行转化:

In [11]: t.decode('utf8')
Out[11]: u'\u4f60\u597d\u4e16\u754c'
In [12]: print u'\u4f60\u597d\u4e16\u754c'
你好世界

2.python3 的文本读写

python3 对字符串的支持更加清晰合理,unicode 就是 python3 中的 str 而 str 就是python3 中的 byte

就比如说,python2 中字符串前面加一个u 才代表 unicode 字符串但是 python3 什么都不用加直接就是,反倒是如果想成为一个 byte 字符串要加 b

python3 的读写可以指定一个参数 encoding = ‘’ 自动的进行编解码

文本的写入:

f = open('test.txt','w',encoding = 'utf8')
f.write("国庆快乐")

文本的读出:

f = open('test.txt','r',encoding='utf8')
t = f.read()
print (t)

二、如何处理二进制文件

wav 是音频问价,前44字节是文件的头信息,我们可以尝试将其读出来

In [6]: f = open('test.wav','rb')
In [7]: info = f.read(44)
In [8]: info
Out[8]: 'RIFFt\x9b\x0b\x00WAVEfmt \x10\x00\x00\x00\x01\x00\x02\x00\x11+\x00\x00D\xac\x00\x00\x04\x00\x10\x00dataP\x9b\x0b\x00'

那么我们如何将其解析出来呢?

我们可以使用 struct 这个库中的unpack 方法

举个例子:

h 是一个 short 的意思

import struct
print struct.unpack('h','\x01\x02')//小端序
print '\n'
print struct.unpack('>h','\x01\x02')//大端序
(513,)//--------->2x256+1
(258,)//--------->1x256+2

比如我们的音频文件的 22-24 字节是声道数,于是我们就能使用这个函数将其解析出来

代码示例:

import struct
f = open('test.wav','rb')
info = f.read(44)
print struct.unpack('h',info[22:24])

结果:

(2,)

说明这个音频文件是双声道

再比如我们想读音频文件的采样频率,这个东西是24-28 4个字节

代码示例:

import struct
f = open('test.wav','rb')
info = f.read(44)
print struct.unpack('i',info[24:28])//因为这里是4个字节所以我们就是用的i

结果:

(11025,)

综合实验:

我们现在想读入音频文件的数据部分,并且不能以字符串的形式,因为字符串的形式没法进行输入操作,我们可以将其以每两个字节为一组读入一个buf

我们首先看一下我们的音频的数据有多大:

import array
f = open('test.wav', 'rb')
f.seek(0, 2) # 移动指针的位置
t = f.tell() # 返回指针的位
a = (t-44)/2 # 每两个一组进行分组
print a

a 就是最终的组数

然后我们就创建指定类型大小的Buf,我们把buf初始化,并将44字节以后的输入写入buf

buf = array.array('h',(0 for _ in xrange(a)))
f.seek(44)
f.readinto(buf)

接下来我们对 buf 进行操作,将操作完的结果重新写成另一个文件

info = f.read(44)

for i in xrange(a):

buf[i]/=8

f2 = open('demo.wav','wb')
f2.write(info)
buf.tofile(f2)
f2.close()

以上步骤,我们其实已经将我们的音频声音变成了原来的1/8

代码示例:

# coding=utf-8
import struct
import array
f = open('test.wav', 'rb')
info = f.read(44)
f.seek(0, 2) # 移动指针的位置
t = f.tell() # 返回指针的位置
a = (t-44)/2
buf = array.array('h',(0 for _ in xrange(a)))
f.seek(44)
f.readinto(buf)
for i in xrange(a):
 buf[i]/=8
f2 = open('demo.wav','wb')
f2.write(info)
buf.tofile(f2)
f2.close()

三、如何设置文件的缓冲

将文件写入硬件设备的时候是按照块进行写入的,每个块有固定的大小,也就是说,进行一次写入操作的时间是固定的,不管你有没有把块填满,因此如果没有缓冲,就会在块不满的情况下进行写入,导致次数过多时间过长,于是我们需要设置文件缓冲。

缓冲又分为全缓冲和行缓冲,一般文件的缓冲就是全缓冲,意思就是填满一个就释放一个,而行缓冲就是遇到换行符就释放。

当然并不是所有的设备都需要缓冲的,串口设备我们就希望能即时发送,于是我们不设置缓冲区

1.检验缓冲区大小实验:

ipython :

In [13]: f = open(‘demo.txt’,’w’)

In [14]: f.write(‘abc’)

In [15]: f.write(‘+’*4093)

In [16]: f.write(‘-‘)

另一个终端:

$ tail -f demo.txt

14、15 命令执行以后 tail 都没反应,直到16命令执行,在tail 后面输出了 abc和 4093个*,可见缓冲区的大小是4096字节

2.修改默认缓冲区的大小

(1)全缓冲:

open 函数 有一个 buffering 的选项可以设置缓冲区大小,我们设置为大于一的整数

f = open('demo.txt','w',buffering = 2048)

(2)行缓冲:

将 buffering 设置为1

f = open('demo.txt','w',buffering = 1)

(3)无缓冲:

将 buffering 设置为0

f = open('demo.txt','w',buffering = 0)

四、如何将文件映射到内存

需求:

1.在访问二进制文件的时候,希望把文件映射到内存空间,实现随机访问

2.嵌入式设备中,寄存器被编址到内存地址空间,我们可以映射 /dev/mem 的某些范围,来操纵这些寄存器

3.如果多个进程映射同一个文件,还能实现进程通信

使用 mmap.mmap()

通过下面这条命令创建一个1M的全0文件:

dd if=/dev/zero of=demo.bin bs=1024 count=1024

使用 od -x 查看,发现的确是全0

od -x demo.bin

0000000 0000 0000 0000 0000 0000 0000 0000 0000

*

4000000

我们获取文件描述符

示例代码:

f = open('demo.bin','r+b')
print f.fileno()

结果:

我们将整个文件映射到变量m

m = mmap.mmap(num,0,mmap.ACCESS_WRITE) # 这里的0表示的是全部文件

我们看一下内容:

In [10]: m[100]
Out[10]: '\x00'

修改:

In [11]: m[100] = '\x08'

查看修改后的内容

In [12]: m[99:120]
Out[12]: '\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

实际上在这种情况下文件已经被修改。

我们还可以跳过整数倍的页的大小对文件进行修改(页的概念来源于操作系统,如果不了解可以去查一下)

m = mmap.mmap(num,mmap.PAGESIZE*8,mmap.ACCESS_WRITE,offset = mmap.PAGESIZE*4)

五、如何访问文件的状态

在某些项目中我们需要获取文件的状态,

比如:

(1)文件类型

(2)文件权限

(3)文件最后修改时间

(4)文件的大小

方法一:系统调用

1.os.stat()

2.os.lstat()

它与os.stat 的区别在于它不跟随符号链接文件,意思就是lstat 拿到的是快捷方式的属性,而stat 拿到的是原始文件的属性

3.os.fstat()

这个函数和上面两个函数的区别是这个函数传入的参数是文件描述符,而不是上面两个参数传入的路径。

示例代码:

In [3]: import os
In [4]: os.stat('demo.bin')
Out[4]: posix.stat_result(st_mode=33188, st_ino=264254, st_dev=2049, st_nlink=1, st_uid=0, st_gid=0, st_size=1048576, st_atime=1538365252, st_mtime=1538364797, st_ctime=1538364797)

查看文件的类型:

文件的类型就存储在 st_mode 里面,我们需要将其解析

In [15]: import os
In [16]: s = os.stat('demo.bin')
In [17]: import stat
In [18]: stat.S_ISDIR(s.st_mode)
Out[18]: False

查看文件的权限

In [19]: s.st_mode & stat.S_IRUSR
Out[19]: 256

只要这个返回值大于0就说明有用户读的权限

In [20]: s.st_mode & stat.S_IXUSR
Out[20]: 0

可见用户的执行权限是0

查看文件的最后访问时间:

In [25]: import time
In [26]: time.localtime(s.st_atime)
Out[26]: time.struct_time(tm_year=2018, tm_mon=10, tm_mday=1, tm_hour=11, tm_min=40, tm_sec=52, tm_wday=0, tm_yday=274, tm_isdst=0)

方法二:快捷函数

快捷函数在底层实现上是利用的是系统函数,但是会让你操作起来更加方便

判断文件类型:

In [27]: os.path.isdir('demo.bin')
Out[27]: False
In [28]: os.path.isfile('demo.bin')
Out[28]: True

判断文件最后访问时间:

In [32]: time.localtime(os.path.getatime('demo.bin'))
Out[32]: time.struct_time(tm_year=2018, tm_mon=10, tm_mday=1, tm_hour=11, tm_min=40, tm_sec=52, tm_wday=0, tm_yday=274, tm_isdst=0)

六、如何使用临时文件:

比如我们采集数据进行分析,但是我们只需要保存结果,我们采集的数据如果常驻内存就会让电脑崩溃,于是我们将这个数据放在临时文件中(外部存储),在文件关闭后将被删除

示例代码:

In [15]: from tempfile import TemporaryFile,NamedTemporaryFile
In [16]: f = TemporaryFile()
In [17]: f.write('abc'*10000)
In [18]: f.seek(0)
In [19]: f.read(100)
Out[19]: 'abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabca'

这个临时文件在系统中是找不到的,如果我们想创建一个能在文件系统中看到的临时文件,我们就用NamedTemporaryFile

示例代码:

我们能看到文件路径

In [20]: nte = NamedTemporaryFile()
In [21]: nte.name
Out[21]: 'c:\\users\\k0rz3n\\appdata\\local\\temp\\tmpob51yb'

如果我们重新创建一个文件的话,原来的文件就会被关闭,关闭以后临时文件就会被自动删除,如果我们不想让他删除,我们在创建的时候就要设置一个参数

nte = NamedTemporaryFile(delete = False)

有需要Python学习资料的小伙伴吗?小编整理【一套Python资料、源码和PDF】,感兴趣者可以关注小编后私信学习资料(是关注后私信哦)反正闲着也是闲着呢,不如学点东西啦

相关推荐

Python 数据分析——利用Pandas进行分组统计

话说天下大势,分久必合,合久必分。数据分析也是如此,我们经常要对数据进行分组与聚合,以对不同组的数据进行深入解读。本章将介绍如何利用Pandas中的GroupBy操作函数来完成数据的分组、聚合以及统计...

python数据分析:介绍pandas库的数据类型Series和DataFrame

安装pandaspipinstallpandas-ihttps://mirrors.aliyun.com/pypi/simple/使用pandas直接导入即可importpandasas...

使用DataFrame计算两列的总和和最大值_[python]

【如果对您有用,请关注并转发,谢谢~~】最近在处理气象类相关数据的空间计算,在做综合性计算的时候,DataFrame针对每列的统计求和、最大值等较为方便,对某行的两列或多列数据进行求和与最大值等的简便...

8-Python内置函数

Python提供了丰富的内置函数,这些函数可以直接使用而无需导入任何模块。以下是一些常用的内置函数及其示例:1-print()1-1-说明输出指定的信息到控制台。1-2-例子2-len()2-1-说...

Python中函数式编程函数: reduce()函数

Python中的reduce()函数是一个强大的工具,它通过连续地将指定的函数应用于序列(如列表)来对序列(如列表)执行累积操作。它是functools模块的一部分,这意味着您需要在使用它之...

万万没想到,除了香农计划,Python3.11竟还有这么多性能提升

众所周知,Python3.11版本带来了较大的性能提升,但是,它具体在哪些方面上得到了优化呢?除了著名的“香农计划”外,它还包含哪些与性能相关的优化呢?本文将带你一探究竟!作者:BeshrKay...

最全python3.11版12类75个内置函数大全

获取全部内置函数:importbuiltins#导入模块yc=[]#异常属性nc=[]#不可调用fn=[]#内置函数defll(ty=builtins):...

软件测试笔试题

测试工程师岗位,3-5年,10-14k1.我司有一款产品,类似TeamViewer,向日葵,mstsc,QQ远程控制产品,一个PC客户端产品,请设想一下测试要点。并写出2.写出常用的SQL语句8条,l...

备战各大互联网巨头公司招聘会,最全Python面试大全,共300题

前言众所周知,越是顶尖的互联网公司在面试这一part的要求就越高,需要你有很好的技术功底、项目经验、一份漂亮的简历,当然还有避免不了的笔试过关。对于Python的工程师来说,全面掌握好有关Python...

经典 SQL 数据库笔试题及答案整理

马上又是金三银四啦,有蛮多小伙伴在跳槽找工作,但对于年限稍短的软件测试工程师,难免会需要进行笔试,而在笔试中,基本都会碰到一道关于数据库的大题,今天这篇文章呢,就收录了下最近学员反馈上来的一些数据库笔...

用Python开发日常小软件,让生活与工作更高效!附实例代码

引言:Python如何让生活更轻松?在数字化时代,编程早已不是程序员的专属技能。Python凭借其简洁易学的特点,成为普通人提升效率、解决日常问题的得力工具。无论是自动化重复任务、处理数据,还是开发个...

太牛了!102个Python实战项目被我扒到了!建议收藏!

挖到宝了!整整102个Python实战项目合集,从基础语法到高阶应用全覆盖,附完整源码+数据集,手把手带你从代码小白变身实战大神!这波羊毛不薅真的亏到哭!超全项目库,学练一站式搞定这份资...

Python中的并发编程

1.Python对并发编程的支持多线程:threading,利用CPU和IO可以同时执行的原理,让CPU不会干巴巴等待IO完成。多进程:multiprocessing,利用多核CPU...

Python 也有内存泄漏?

1.背景前段时间接手了一个边缘视觉识别的项目,大功能已经开发的差不多了,主要是需要是优化一些性能问题。其中比较突出的内存泄漏的问题,而且不止一处,有些比较有代表性,可以总结一下。为了更好地可视化内存...

python爬虫之多线程threading、多进程、协程aiohttp批量下载图片

一、单线程常规下载常规单线程执行脚本爬取壁纸图片,只爬取一页的图片。importdatetimeimportreimportrequestsfrombs4importBeautifu...

取消回复欢迎 发表评论: