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

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

文件打开关闭

打开

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

  1. 语法格式:

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

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

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

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

    运行结果:

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

关闭

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

文件的写入

将 hello world 写入test.txt 文件中

w-只写

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

运行结果:

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

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

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

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

wb-只二进制写

01字符串

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

报错:

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

修改后运行结果:

a-只追加写

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

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

报错:

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

修改后报错:

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

修改后运行结果:

ab-只二进制追加

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

运行结果:

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

文件的读取

read()

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

案例:读取test.txt文件

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

运行结果:

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

readline()

读取一行

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

运行结果:

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

readlines()

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

1
2
3
4
5
6
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

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

    运行结果:

  2. with关键字

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

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

    运行结果:

文件备份脚本

小文件

1
2
3
4
5
6
7
8
9
10
11
12
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()一次读取全部会消耗较大内存。

大文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

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

1
2
3
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个字节的内容

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

运行结果:

seek

设置文件指针的位置

  1. 语法:

    1
    f.seek(offset,from)

    注意:

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

    1
    2
    3
    4
    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. 导入和使用:

    1
    2
    3
    import time  # 导入

    print(time.ctime()) # 调用

    运行结果:

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

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

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

    • sys模块中搜索:

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

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

    1
    2
    3
    import time as t  # 别名为t

    print(t.ctime()) # 模块名称不可使用

    运行结果:

from…import

只导入其中部分函数

  1. 导入和使用:

    1
    2
    3
    from time import ctime, time  # 导入两个函数,不需要添加括号

    print(ctime()) # 不再需要模块名称

    导入全部:

    1
    2
    3
    from time import *  # 导入全部函数

    print(ctime()) # 不再需要模块名称

    运行结果:

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

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

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

os模块

  1. 重命名:

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

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

    • 创建一级目录:

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

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

    • 删除空目录:

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

      1
      2
      3
      import shutil as st

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

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

    • os.listdir():

      1
      2
      3
      4
      5
      import os

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

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

      运行结果:

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

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

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

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

  8. 其它的一些操作:

制作模块

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

  1. 模块内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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. 导入模块:

    1
    2
    3
    4
    import modudelTest  # 导入自定义模块

    rs = modudelTest.add(1, 1)
    print('测试结果:', rs)

    运行结果:

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def add(a, b):
    '''
    返回a与b的和
    :param a: 数a
    :param b: 数b
    :return: a+b
    '''
    return a + b


    # 测试
    print('__name__的值是:', __name__)
    • 运行模块文件:

    • 导入模块:

      1
      import modudelTest  # 导入自定义模块

      运行结果:

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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中存在的函数名

    • 模板内容:

      1
      2
      3
      4
      5
      6
      7
      8
      __all__ = ['add', 'diff']  # 魔术变量__all__

      def add(a, b):
      return a + b
      def diff(a, b):
      return a - b
      def printInfo():
      return '这是输出的信息'
    • 使用import导入模板:

      1
      2
      3
      4
      5
      import modudelTest  # 导入自定义模块

      print(modudelTest.add(1, 2))
      print(modudelTest.diff(5, 4))
      print(modudelTest.printInfo())

      运行结果:

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

      1
      2
      3
      4
      5
      from modudelTest import *

      print(add(1, 2))
      print(diff(5, 4))
      print(printInfo())

      运行结果:

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

发布模块

让其他开发者安装后使用

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    from distutils.core import setup

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

    1
    python setup.py build

    运行结果:

  4. 生成压缩包:

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

安装模块

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

    1
    pip install moduelTest-1.0.tar.gz

    运行结果:

  2. 使用模块:

    1
    2
    3
    import modudelTest as mt

    print(mt.add(1, 5))

    运行结果:


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

创作不易,感谢支持!