python中基于OS模块的文件操作

一 文件操作要求
生成一个文件 ips.txt ,要求120000行,每行随机为172.25.154.0/24段的ip
读取ips.txt文件统计这个文件中ip出现频率排前10的ip

import random

with open('ips.txt', "w") as f:
    for i in range(240000):
        f.write('172.25.254.' + str(random.randint(1, 254)) + '\n')

from collections import Counter


def most_count(filename='ips.txt', n=10):
    with open(filename) as f:
        count = Counter(f)
    return [i[0].strip() for i in count.most_common(n)]


print(most_count())

二 文件的读取
文件读取三部曲:打开—> 操作—>关闭
1)打开

f=open('/etc/passwd')
print(f)

这里写图片描述
可以看到,是一个对象,如果要看到其内容,需对其进一步操作
2)操作

content=f.read()
print(content)

这里写图片描述
通过read来进行对文件的查看
3)关闭

f.close()

关闭文件
4)对文件操作时的权限
open(文件名,权限设置)
如果不对权限进行设置:权限设置默认为 r 权限
此处共有6中权限,分别为:
r:只能执行读的权力,没有写的权力,当读取的文件不存在时,会报错
r+:可以执行读写操作,默认情况下,从文件指针所在位置开始写入,当读取的文件不存在时,会报错
w:只有写入的权限,但是当写入时,会先清空文件内容,当文件不存在时,会生成此文件,不会报错
w+:可以执行读写操作,但是当写入时,会先清空文件内容,当文件不存在时,会生成此文件,不会报错
a:只有写入的权力,写入时,不会清空文件内容,当文件不存在时,会生成此文件,不会报错
a+:可以执行读写的权力,写入时,不会清空文件内容,当文件不存在时,会生成此文件,不会报错
5)判断文件的权限,是否具有读与写的权限

print(f.readable())
print(f.writable())

这里写图片描述
如果可读或可写的话,返回True,否则,返回False
三 非纯文本文件的读取
如果读取图片, 音乐或者视频(非文本文件), 需要通过二进制的方式进行读取与写入;b

#先对图片进行读取,保存到一个文件中
f1=open('hello.png','rb')
content=f1.read()
f1.close()
#再对新的图片,将该文件内容进行写入复制
f2=open('world.png','wb')
f2.write(content)
f2.close()

这里写图片描述
可以看到图片world.png的成功建立
四 文件的常用属性
1) suffer(缓冲区对象)

f=open('/mnt/passwd')
#buffer缓冲区对象
print(f.buffer)

这里写图片描述
suffer就是一个缓冲区对象
那么怎样来对缓冲区的内容进行读取呢
这里写图片描述
将缓冲区对象赋值给一个变量,通过遍历变量的内容来读取缓冲区的内容
这里写图片描述
当只是读取文件时, buffer里面没有内容
这里写图片描述
此时写入的内容在缓冲区里面,并没有真正写入磁盘文件
只有再执行 f.close 的时候,写入的内容才会真正的写入磁盘当中
2) 判断文件对象是否关闭,
用 f.closed 来判断
已经关闭返回True,否则,返回False
3) 文件号

f=open('/mnt/passwd')
print(f.fileno())

这里写图片描述
文件号为3
4) 文件对象

f=open('/mnt/passwd')
print(f.name)

这里写图片描述
文件命可以看到为 /mnt/passwd
5) 查看文件对象的相关信息

f=open('/mnt/passwd')
print(f)

这里写图片描述
可以看到它的名字,权限等
五 文件的常用方法
1) 读取文件内容

f.read()

默认情况下读取全部内容,小的文件用read读取
大的文件(文件大小> 内存大小),不能通过read直接读取

r.read(3)

这里写图片描述
类似于 head -c 3 /mnt/passwd 命令(读取前三个字符)
要通过read的其它指令来进行读取

f.readline

这里写图片描述
每次读取一行内容

f.readlines

这里写图片描述
读取文件的所有内容, 返回一个列表, 列表元素分别为文件行内容
可以看到每一行后面都有一个换行符,那么如果去掉它呢
可以通过(列表生成式或者是map函数)

print([line.strip() for line in f.readlines()])
print(list(map(lambda x:x.strip(),f.readlines())))

这里写图片描述
可以看到后面的换行符被去掉了
2) 文件的写入

f.write('hello')

从指针所在位置写入, 写入是字符串内容

f.writelines

这里写图片描述
将列表里面的每个元素写入文件中
3) 指针位置的操作

f.tell

显示当前指针的位置

f.seek

移动指针(x,y)—–>(x:指针偏移的量)(y=0:移动到最开始;y=2:移动到最后)

f=open('/mnt/passwd','r+')
#指针目前所在的位置
print(f.tell())
print('1: ',f.read(5))
print('指针移动之前:',f.tell())
f.seek(0,0)
f.write('lion')
print('指针移动之后:',f.tell())
print('2: ',f.read())
f.close()

六 文件的安全读取
1)上下文管理器
上下文管理器:打开文件, 执行完with语句内容之后, 自动关闭文件对象

# 相当于 f=open('/mnt/passwd')
with open('/mnt/passwd') as f:
    print('with语句里面:',f.closed)
    print(f.read())
print('after with:',f.closed)

这里写图片描述
当你用 with 写完打开写完时,自动关闭文件
2)可同时打开两个文件对象

# 同时打开两个文件对象
with open('/mnt/passwd') as f1, \
     open('/mnt/passwdBack','w+') as f2:
    #将第一个文件内容写入第二个文件中
    f2.write(f1.read())
    #移动指针到文件最开始
    f2.seek(0,0)
    #从指针位置开始读取内容
    print(f2.read())

这种写法python2中,不支持。python2中只能嵌套使用

with open('/mnt/passwd') as f1:
    content=f1.read()
with open('/mnt/passwdBack','w+') as f2:
    print(f2.write(content))

七 yield实现读取大文件
文件操作需求:
1. 创建文件data.txt, 文件共100000行, 每行存放一个1~100之间的整数.
2. 找出文件中数字出现次数最多的10个数字, 写入文件mostNum.txt

import random
with open('data.txt','a+')as f:
    for i in range(100000):
        f.write(str(random.randint(1,100))+'\n')

先随机生成这么多行来存放整数

# 通过yield,每次读取一行进行处理
def bylineReader(filename):
    with open(filename)as f:
        line=f.readline()
        #如果可以读取到内容,返回该行信息
        while line:
            yield line
            line=f.readline()
# read是生成器对象
read=bylineReader('data.txt')
print(read)

这里写图片描述
如何来对生成器内容进行读取,可以通过(next方法),也可以通过(for循环遍历)

# 1)next 读取生成器内容
print(next(read))
print(next(read))
# 2)for 读取生成器内容
for item in read:
    print(item)

当然如果一遍一遍的next的话,显然是有点麻烦的,我们在这里采用for循环遍历

# 文件对象是可以for循环便历的,默认便历的内容为每一行的内容,是节省空间的
from collections import Iterator
f=open('data.txt')
print(isinstance(f,Iterator))
for  i,item in enumerate(f):
    if i==10:
        break
    print(item)

对其判断是否可以进行迭代,返回True,来对其进行遍历,遍历前10行的内容
八 读取文件方式效率的比较
前面我们做了一个时间比较的装饰器,在这里我们就可以直接调用了

from my_TM import timeit


@timeit
def read1(filename):
    # 迭代
    with open(filename) as f:
        for line in f:
            # 对文件进行操作
            line = int(line.strip())
            line = line + 1


@timeit
def read2(filename):
    with open(filename)as f:
        for line in f.readlines():
            # 对于文件进行操作
            line = int(line.strip())
            line = line + 1


read1('data.txt')
read2('data.txt')

这里写图片描述
可以看到直接遍历文件和读取文件全部内容后再直接遍历内容,时间好像差不多,
这可能是我们的文件太小,对文件的操作太简单的原因
九 os模块中环境变量函数
首先我们导入os模块

import os

1) 返回操作系统类型, 值为posix,是Linux操作系统, 值为nt, 是windows操作系统

import os
print(os.name)
print('Linux' if os.name=='posix' else 'Windows')

这里写图片描述
2) 操作系统的详细信息

info = os.uname()
print(info)
print(info.sysname)
print(info.nodename)

这里写图片描述
uname 用来查看详细的操作信息
3) 系统环境变量

print(os.environ)

这里写图片描述
enciron 查看系统的环境变量
4) 通过key值获取环境变量对应的value值

print(os.environ.get('PATH'))
print(os.getenv('PATH'))

这里写图片描述
系统中环境变量的信息是用字典存储的,因此可以用 key来获取环境变量的value值
十 os模块中文件的操作
1) 判断是否为绝对路径

import os
print(os.path.isabs('/tmp/hello'))
print(os.path.isabs('hello'))

这里写图片描述
如果是绝对路径,则返回True,否则返回False
2) 生成绝对路径

import os
print(os.path.abspath('/tmp/hello'))
print(os.path.abspath('hello.png'))

这里写图片描述
如果已经是绝对路径,则不变,而相对路径则转换为绝对路径
当前目录的绝对路径+ 文件名/目录名
3) 获取目录名或者文件名

filename = '/home/kiosk/Desktop/201808python/day10/hello.png'
print(os.path.basename(filename))
print(os.path.dirname(filename))

这里写图片描述
获取文进的目录以及当前的文件名
4) 创建目录/删除目录

os.mkdir('img')

创建目录

os.makedirs('img/films')

创建多层目录

os.rmdir('img')

删除目录
5) 创建文件/删除文件

os.mknod('00_ok.txt')

创建文件

os.remove('00_ok.txt')

删除文件
6) 文件重命名

os.rename('00_ok.txt', 'data.txt')

7) 判断文件或者目录是否存在

print(os.path.exists('img'))

这里写图片描述
如果存在,则返回True
8) 分离后缀名和文件名

print(os.path.splitext('hello.png'))
print(os.path.split('hello.png'))

这里写图片描述
9) 分离目录名与文件名

print(os.path.split('/tmp/hello/hello.png'))

这里写图片描述
10)例:
1)在当前目录新建目录img, 里面包含100个文件, 100个文件名各不相同
2)将当前img目录所有以.png结尾的后缀名改为.jpg

import os
import random
from os.path import exists, splitext, join
import string
def gen_code(len=4):
    # 随机生成4位的验证码
    li = random.sample(string.ascii_letters+string.digits, len)
    # 将列表元素拼接为字符串
    return  "".join(li)

def create_files():
    # 随机生成100个验证码
    li = {gen_code() for i in range(100)}

    os.mkdir('img')
    # # 随机生成四个数字
    for name in li:
        os.mknod('img/' + name  + '.png')
def modify_suffix(dirname, old_suffix, new_suffix):
    """
    :param dirname: 操作的目录
    :param old_suffix: 原先的后缀名
    :param new_suffix: 新的后缀名
    :return:
    """
    # 1. 判断查找的目录是否存在, 如果不存在, 显示报错
    if exists(dirname):
        # 2. 找出所有以old_suffix(.png)结尾的
        # pngfiles = [ filename for filename in os.listdir(dirname)
        #             if filename.endswith(old_suffix)]
        pngfiles = filter(lambda filename: filename.endswith(old_suffix), os.listdir(dirname))
        # 3. 将文件名和后缀名分开, 留下所有的文件名
        basefiles = [splitext(filename)[0] for filename in pngfiles]
        print(basefiles)
        # 4. 文件重命名
        for filename in basefiles:
            # 需要加上目录名
            oldname = join(dirname, filename + old_suffix)
            newname = join(dirname, filename + new_suffix)
            os.rename(oldname, newname)
            print("%s重命名为%s成功" % (oldname, newname))
    else:
        print("%s不存在, 不能操作......" % (dirname))        

假若,别人要调用此模块,来完成后缀名的更改

# 如果该脚本没有被调用, 则执行下面的代码;
import sys
if __name__ == '__main__':
    # **** 如何在执行脚本时, 接收用户传入的参数;
    # 判断用户传的参数是否为3个参数?
    if len(sys.argv) == 4:
        dirname = sys.argv[1]
        old_suffix = sys.argv[2]
        new_suffix = sys.argv[3]
        # modify_suffix('img', '.png', '.jpg')
        modify_suffix(dirname, old_suffix, new_suffix)
    else:
        print("""
    Usage: %s dirname old_suffix new_suffix

        """ % (sys.argv[0]))

问题在于如何判断传入的参数为3个
那么,还可以这样:

import  optparse 
# 如果该脚本没有被调用, 则执行下面的代码;
if __name__ == '__main__':
    # **** 如何在执行脚本时, 接收用户传入的参数;
    # 判断用户传的参数是否为3个参数?
    # 实例化对象
    parser = optparse.OptionParser()
    # add_option, ‘-d’, 选项的短名称,
    #  dest: 接收-d后面的参数, 存放到变量dirname里面, type指定传递的数据类型.
    parser.add_option('-d', '--dirname', dest='dirname', type=str)
    parser.add_option('-o', '--oldSuffix', dest='oldSuffix', type=str)
    parser.add_option('-n', '--newSuffix', dest='newSuffix', type=str)
    (opt, args) = parser.parse_args()

    modify_suffix(opt.dirname, opt.oldSuffix, opt.newSuffix)

两种方法都可以,取决于你导入的模块
十一 遍历目录下的内容

import os

from os.path import join

for root, dirs, files in os.walk('/var/log'):
    # print(root, dirs, files)
    for name in files:
        print(join(root, name))

这里写图片描述
通过导入os模块来查看目录当中的内容

猜你喜欢

转载自blog.csdn.net/weixin_42668123/article/details/81989266
今日推荐