Day11文件操作和模块

本文章最初发布在 XJHui’s Blog,未经允许,任何人禁止转载!

注意:最新修改版本已发布在 这里,点击前往查看!

文件打开关闭

打开

使用open函数,可以打开已存在的文件或者创建一个新文件

  1. 语法格式:

    open('文件名称','打开模式')  # 打开模式也要使用引号
    
  2. 示例:

    open('test.txt','w')  
    
  3. 文件打开模式:

  4. 案例:使用w打开模式,打开Test.txt文件

    open('./Test.txt', 'w')  # 打开一个不存在的文件
    

    运行结果:

    注意:打开模式为w时,若文件不存在则会自动创建

关闭

fobj = open('./Test.txt', 'w')  # open函数返回文件对象,使用fobj接受这个对象
fobj.close()  # 使用:文件对象.close() 关闭打开的文件

文件的写入

将 hello world 写入test.txt 文件中

w-只写

fobj = open('./test.txt', 'w')  # 使用open函数在w打开模式下打开test.txt文件
fobj.write('hello world')  # 使用:文件对象.write(要写入的内容) 将字符串写入文件
fobj.close()  # 写入后记得要关闭

运行结果:

注意:默认的编码是gbk,为防止乱码:

  • 方法一(打开文件时):

    fobj = open('./test.txt', 'w', encoding='utf-8')
    
  • 方法二(写入文件时):

    obj.write('hello world'.encode('utf-8')) 
    

wb-只二进制写

01字符串

fobj = open('./test.txt', 'wb')
fobj.write('hello world')
fobj.close()

报错:

注意:wb写入时,要指定写入值的类型 obj.write('hello world'.encode('utf-8'))

修改后运行结果:

a-只追加写

追加:存在则在原来基础上接着写,不存在则从头写

fobj = open('./test.txt', 'a')
fobj.write('这是追加的内容'.encode('utf-8'))
fobj.close()

报错:

注意:a打开模式,写入内容必须是字符串,不需要添加encode。

修改后报错:

注意:虽然是字符串类型写入的,但打开后依然显示乱码,在打开文件时使用 encoding = 'utf-8'

修改后运行结果:

ab-只二进制追加

fobj = open('./test.txt', 'ab')
fobj.write('\n这还是追加的内容'.encode('utf-8'))
fobj.close()

运行结果:

注意:’\n’在写入时表示换行符!

文件的读取

read()

read()表示读取全部内容,r打开模式下:read(2)读取前两个字符,rb模式下表示读取前两个字节

案例:读取test.txt文件

f = open('test.txt', 'r', encoding='utf-8')  # 打开模式使用r(只读)
print(f.read(10))  # 读取10个字符
print('---------------')
print(f.read())  # 读取全部内容
f.close()

运行结果:

注意:第二个read()开始读取的位置为第一个read()读取结束的位置+1。

readline()

读取一行

f = open('test.txt', 'r', encoding='utf-8')
print(f.readline())
print(f.readline())
f.close()

运行结果:

注意:每行最后都会跟一个空行,想避免这个问题可以使用end=''

readlines()

按行读取所有内容并将读取到的数据存入列表中

f = open('test.txt', 'r', encoding='utf-8')  # 使用r打开模式,打开文件
dataList = f.readlines()  # readlines()读取文件所有内容
print(type(dataList))  # 打印存放读取数据的列表
for item in dataList:  # 遍历该列表,输出文件内容
    print(item, end='')  # 使用end='' 避免出现空行的问题
f.close()  # 关闭文件

运行结果:

补充

  1. 解码:decode

    f = open('test.txt', 'rb')  # 二进制读取
    data = f.read()
    print(data.decode('utf-8'))  # decode解码
    f.close()
    

    运行结果:

  2. with关键字

    使用open()函数打开文件后,容易忘记关闭文件,使用with关键字打开文件可避免因此带来的问题

    with open('test.txt', 'r', encoding='utf-8') as f:
        print(f.read())
    

    运行结果:

文件备份脚本

小文件

def smallFileCopy():
    old_name = input('请输入要备份的文件名:')
    old_nameList = old_name.split('.')
    new_name = old_nameList[0] + '备份.' + old_nameList[1]
    with open(old_name, 'r', encoding='utf-8') as old_file, open(new_name, 'w', encoding='utf-8') as new_file:  # 要同时打开多个文件是,可以只使用一个with,多个open()之间使用逗号分隔
        fileData = old_file.read()
        new_file.write(fileData)
        pass
    pass


smallFileCopy()

运行结果:

注意:该代码仅适用于小型文件,因为使用read()一次读取全部会消耗较大内存。

大文件

def bigFileCopy():
    old_name = input('请输入要备份的文件名:')
    old_nameList = old_name.split('.')
    new_name = old_nameList[0] + '备份.' + old_nameList[1]
    with open(old_name, 'r', encoding='utf-8') as old_file, open(new_name, 'w', encoding='utf-8') as new_file:
        while True:
            fileData = old_file.read(1024)
            new_file.write(fileData)
            if len(fileData) < 1024:
                break
            pass


bigFileCopy()

运行结果:

注意:每次读取固定大小字符,避免一次读取过多内容。

文件定位

tell

获取文件指针位置(字节)

with open('test.txt', 'r', encoding='utf-8') as f:
    print(f.read(6))  # 读取6个字符
    print(f.tell())  # 打印文件指针位置

运行结果:

注意:

  • utf-8编码下:汉字所占字节数为3
  • gbk编码下:汉字所占字节数为2
  • 英文所占字节数,在上面两种编码下均为1个

案例中所用编码格式为utf-8,共读取6个字符,故文件指针位置在第3*6=18个字节处

truncate

f.truncate(10):保留前10个字节的内容

with open('test.txt', 'r+', encoding='gbk') as f:  # gbk编码格式,每个中文占2个字节
    f.truncate(10)  # 字节
    print('-------截取后文件的内容:-------')
    print(f.read())

运行结果:

seek

设置文件指针的位置

  1. 语法:

    f.seek(offset,from)
    

    注意:

    • offset:表示偏移量(字节,为负表示向前移动)
    • from:0-从头,1-从当前位置,2-从文件末尾
  2. 案例1:seek的简单使用

    with open('test备份.txt', 'rb') as f:
        print(f.read(3).decode('utf-8'))
        f.seek(-3, 1)  # 文件指针回溯3个字节
        print(f.read(6).decode('utf-8'))
    

    运行结果:

  3. 当文件打开方式为非二进制时,只允许从文件的开头计算相对位置。

模块

import

导入模块中所有的功能

  1. 导入和使用:

    import time  # 导入
    
    print(time.ctime())  # 调用
    

    运行结果:

  2. 首次导入模块时,系统的操作:

    • 打开模块文件
    • 执行该文件,将执行过程中产生的名字都丢到模块的名称空间
    • 在程序中会有一个模块的名称指向模块的名称空间去
  3. 模块搜索路径:

    • 优先搜索当前目录(自定义模块中的函数名不要和系统中的重复)

    • sys模块中搜索:

    • 第三方模块默认安放位置:

      • linux:/usr/local/lib/python
      • windows:环境变量位置\Lib\site-package
  4. as 起别名:

    import time as t  # 别名为t
    
    print(t.ctime())  # 模块名称不可使用
    

    运行结果:

from…import

只导入其中部分函数

  1. 导入和使用:

    from time import ctime, time  # 导入两个函数,不需要添加括号
    
    print(ctime())  # 不再需要模块名称
    

    导入全部:

    from time import *  # 导入全部函数
    
    print(ctime())  # 不再需要模块名称
    

    运行结果:

  2. 首次导入模块时,系统的操作:

    • 以模块为准创建一个名称空间
    • 执行该模块文件,将执行过程中产生的名字都丢到模块的名称空间
    • 在程序中拿到一个名字,该名字直接指向模块中的某一个名字

    缺点:容易与本地文件中的函数名称冲突

os模块

  1. 重命名:

    os.rename('test.txt', 'test_重命名.txt')
    
  2. 删除文件:

    os.remove('test备份.txt')
    
  3. 创建文件夹:

    • 创建一级目录:

      os.mkdir('hello')
      
    • 创建多级目录:

      os.makedirs('world\hello')
      
  4. 删除文件夹:

    • 删除空目录:

      os.rmdir('hello')
      
    • 删除非空目录:

      import shutil as st
      
      st.rmtree('world')
      
  5. 打印当前程序目录:

    print(os.getcwd())
    
  6. 遍历d盘根目录下文件名称:

    • os.listdir():

      import os
      
      rs = os.listdir('d:/')
      for item in rs:
          print(item)
      
    • os.scandir():

      with os.scandir('d:/') as sc:
          for rs in sc:
              print(rs.name)
      

      运行结果:

      注意:d盘根目录的表示方法 ‘d:/’

  7. 判断是否是目录/文件:

    print(os.path.isdir('world'))  # 返回值为布尔类型
    

    注意:可以通过递归实现打印某个目录下的全部文件

  8. 其它的一些操作:

制作模块

制作模块实现返回两个数的和

  1. 模块内容:

    def add(a, b):
        '''
        返回a与b的和
        :param a: 数a
        :param b: 数b
        :return: a+b
        '''
        return a + b
    
    
    # 测试
    rs = add(1, 2)
    print('测试结果:', rs)
    

    运行结果:

  2. 导入模块:

    import modudelTest  # 导入自定义模块
    
    rs = modudelTest.add(1, 1)
    print('测试结果:', rs)
    

    运行结果:

    注意:导入模块时,其内部的测试代码也会被执行

  3. 模块内输出魔术变量__name__的值:

    def add(a, b):
        '''
        返回a与b的和
        :param a: 数a
        :param b: 数b
        :return: a+b
        '''
        return a + b
    
    
    # 测试
    print('__name__的值是:', __name__)
    
    • 运行模块文件:

    • 导入模块:

      import modudelTest  # 导入自定义模块
      

      运行结果:

    注意:可以看出__name__在模块内和程序内的值是不同的,我们可以通过该特征解决2中的问题

  4. 根据3中性质修改后的模块代码:

    def add(a, b):
        '''
        返回a与b的和
        :param a: 数a
        :param b: 数b
        :return: a+b
        '''
        return a + b
    
    
    # 测试
    if __name__ == '__main__':  # 判断__name__的值决定是否运行下面的代码 
        rs = add(1, 2)
        print('测试结果:', rs)
    
  5. __all__魔术变量:

    当模块中定义了__all__的值,使用from…import * 则只能导入all中存在的函数名

    • 模板内容:

      __all__ = ['add', 'diff']  # 魔术变量__all__
      
      def add(a, b):
          return a + b
      def diff(a, b):
          return a - b
      def printInfo():
          return '这是输出的信息'
      
    • 使用import导入模板:

      import modudelTest  # 导入自定义模块
      
      print(modudelTest.add(1, 2))
      print(modudelTest.diff(5, 4))
      print(modudelTest.printInfo())
      

      运行结果:

    • 使用from…import *导入模板:

      from modudelTest import *
      
      print(add(1, 2))
      print(diff(5, 4))
      print(printInfo())
      

      运行结果:

      报错原因:模板中定义了__all__的值为 [‘add’, ‘diff’],当私用from导入全部函数时,只可导入all中定义的函数

发布模块

让其他开发者安装后使用

  1. 新建文件夹并将模块文件移入其中:

  2. 文件夹中新建setup.py ,按照注释补充模板内容:

    from distutils.core import setup
    
    # name 模块名称
    # version 版本号
    # description 描述
    # author 作者
    # py_modules 要发布的内容
    setup(name="moduelTest", version="1.0", description="两位数加、减法、输出字符串",
          author="XJHui", py_modules=['modudelTest'])  # 不需要写文件后缀
    
  3. 在新建文件夹下执行命令:

    python setup.py build
    

    运行结果:

  4. 生成压缩包:

    python setup.py sdist
    
  5. 找到压缩包,分享后安装即可使用

安装模块

  1. 压缩包所在文件夹中执行命令:

    pip install moduelTest-1.0.tar.gz
    

    运行结果:

  2. 使用模块:

    import modudelTest as mt
    
    print(mt.add(1, 5))
    

    运行结果:


不足之处,欢迎留言,会及时回复,及时更正!

创作不易,感谢支持!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值