全部文章

14输入和输出、文件读写file

输出格式美化

转义字符串特殊字符

  • str(): 函数返回一个用户易读的表达形式。

repr(): 产生一个解释器易读的表达形式。

# repr()可以转义字符串特殊字符
str="我是带有换行符的字符串\n,哈哈哈"
print(str)
print(repr(str))#'我是带有换行符的字符串\n,哈哈哈'
# 这里感觉和之前打的“r"很像[详见:字符串》》》》字符串运算符]
print(r"我是带有换行符的字符串\n,哈哈哈")#我是带有换行符的字符串\n,哈哈哈

# repr()参数可以是任何对象
list1=[{"name":"Tom","age":18},(1,2,3),"啥都能解析?",{"是的!"}]
print(list1)#[{'name': 'Tom', 'age': 18}, (1, 2, 3), '啥都能解析?', {'是的!'}]
print(repr(list1))#[{'name': 'Tom', 'age': 18}, (1, 2, 3), '啥都能解析?', {'是的!'}]

#总结,我感觉没啥用,除了可以转义特殊字符串

对齐方式(靠左靠右居中)

这里有两种方式输出一个平方与立方的表:

>>> for x in range(1, 11):
...     print(repr(x).rjust(2), repr(x*x).rjust(3), end=' ')
...     # 注意前一行 'end' 的使用
...     print(repr(x*x*x).rjust(4))
...
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000

>>> for x in range(1, 11):
...     print('{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x))
...
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000

注意:在第一个例子中, 每列间的空格由 print() 添加。

这个例子展示了字符串对象的 rjust() 方法, 它可以将字符串靠右, 并在左边填充空格。

还有类似的方法, 如 ljust() 和 center()。 这些方法并不会写任何东西, 它们仅仅返回新的字符串。

另一个方法 zfill(), 它会在数字的左边填充 0,如下所示:

>>> '12'.zfill(5)
'00012'
>>> '-3.14'.zfill(7)
'-003.14'
>>> '3.14159265359'.zfill(5)
'3.14159265359'

可选项 : 和格式标识符可以跟着字段名。 这就允许对值进行更好的格式化。 下面的例子将 Pi 保留到小数点后三位:

>>> import math
>>> print('常量 PI 的值近似为 {0:.3f}。'.format(math.pi))
常量 PI 的值近似为 3.142。

在 : 后传入一个整数, 可以保证该域至少有这么多的宽度。 用于美化表格时很有用。

>>> table = {'Google': 1, 'Runoob': 2, 'Taobao': 3}
>>> for name, number in table.items():
...     print('{0:10} ==> {1:10d}'.format(name, number))
...
Google     ==>          1
Runoob     ==>          2
Taobao     ==>          3

如果你有一个很长的格式化字符串, 而你不想将它们分开, 那么在格式化时通过变量名而非位置会是很好的事情。

最简单的就是传入一个字典, 然后使用方括号 [] 来访问键值 :

>>> table = {'Google': 1, 'Runoob': 2, 'Taobao': 3}
>>> print('Runoob: {0[Runoob]:d}; Google: {0[Google]:d}; Taobao: {0[Taobao]:d}'.format(table))
Runoob: 2; Google: 1; Taobao: 3

也可以通过在 table 变量前使用 ** 来实现相同的功能:

>>> table = {'Google': 1, 'Runoob': 2, 'Taobao': 3}
>>> print('Runoob: {Runoob:d}; Google: {Google:d}; Taobao: {Taobao:d}'.format(**table))
Runoob: 2; Google: 1; Taobao: 3

读和写文件

open() 将会返回一个 file 对象,基本语法格式如下:

open(filename, mode)
  • filename:包含了你要访问的文件名称的字符串值。
  • mode:决定了打开文件的模式:只读,写入,追加等。所有可取值见如下的完全列表。这个参数是非强制的,默认文件访问模式为只读(r)。

不同模式打开文件的完全列表:

 

模式 描述
r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
rb 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。
r+ 打开一个文件用于读写。文件指针将会放在文件的开头。
rb+ 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
w 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
wb 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
w+ 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
wb+ 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
a 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
ab 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
a+ 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
ab+ 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

总结:

模式 r r+ w w+ a a+
+ +   +   +
  + + + + +
创建     + + + +
覆盖     + +    
指针在开始 + + + +    
指针在结尾         + +

下图很好的总结了这几种模式:

 

 以下实例将字符串写入到文件 foo.txt 中:

str="第一次写入文件,好紧张"
# 打开一个文件,路径不存在会报错
f = open("./tem/test.txt", "w+", encoding='utf-8')
f.write(str)
# 关闭文件
f.close()
  • 第一个参数为要打开的文件名。
  • 第二个参数描述文件如何使用的字符。 mode 可以是 'r' 如果文件只读, 'w' 只用于写 (如果存在同名文件则将被删除), 和 'a' 用于追加文件内容; 所写的任何数据都会被自动增加到末尾. 'r+' 同时用于读写。 mode 参数是可选的; 'r' 将是默认值。
  • 第三个参数说明了写人的文字编码

此时打开文件 test.txt,显示如下:

本节中剩下的例子假设已经创建了一个称为 f 的文件对象。

f.read()

为了读取一个文件的内容,调用 f.read(size), 这将读取一定数目的数据, 然后作为字符串或字节对象返回。

size 是一个可选的数字类型的参数。 当 size 被忽略了或者为负, 那么该文件的所有内容都将被读取并且返回。

以下实例假定文件 foo.txt 已存在(上面实例中已创建):

str="第一次写入文件,好紧"
# 打开一个文件,路径不存在会报错
f = open("./tem/test.txt", "r+", encoding='utf-8')
f.write(str)
print(f.read())#注意这里读取为空,不知道是不是这时候还没保存
# 关闭文件
f.close()
f = open("./tem/test.txt", "r+", encoding='utf-8')
print(f.read())#第一次写入文件,好紧
f.close()

f.readline()

f.readline() 会从文件中读取单独的一行。换行符为 '\n'。f.readline() 如果返回一个空字符串, 说明已经已经读取到最后一行。

f = open("./tem/test.txt", "r+", encoding='utf-8')
print(f.readline())#第一次写入文件,好紧
f.close()

f.readlines()

f.readlines() 将返回该文件中包含的所有行。

如果设置可选参数 sizehint, 则读取指定长度的字节, 并且将这些字节按行分割。

f = open("./tem/test.txt", "r+", encoding='utf-8')
print(f.readlines())#['第一次写入文件,好紧\n', '这是第二行了\n', '这是第三行了啊\n', '我去,第四行了\n', '\n']

另一种方式是迭代一个文件对象然后读取每行:

for line in f:
    print(line)
f.close()

这个方法很简单, 但是并没有提供一个很好的控制。 因为两者的处理机制不同, 最好不要混用。

f.write()

f.write(string) 将 string 写入到文件中, 然后返回写入的字符数。

str="这是六个汉字"
f = open("./tem/test.txt", "r+", encoding='utf-8')
num = f.write(str)
print(num)#6
f.close()

如果要写入一些不是字符串的东西, 那么将需要先进行转换:

tuple1=("我是元组","YES",18)
f = open("./tem/test.txt", "r+", encoding='utf-8')
f.write(str(tuple1))
f.close()

f.tell()

f.tell() 用于返回文件当前的读/写位置(即文件指针的位置)。文件指针表示从文件开头开始的字节数偏移量。f.tell() 返回一个整数,表示文件指针的当前位置。

f.seek()

f.seek() 是 Python 中用于移动文件指针位置的方法,其作用是精确控制文件读写的起始位置。下面我来清晰梳理它的用法:

基本语法

f.seek(offset, whence)
 
  • 两个参数
    1. offset:偏移量(整数),表示要移动的字节数(正数向前移动,负数向后移动)。
    2. whence:基准位置(整数),规定从哪里开始计算偏移量,有 3 种取值:
      • 0:以文件开头为基准(默认值,可省略)
      • 1:以当前指针位置为基准
      • 2:以文件末尾为基准

from_what 值为默认为0,即文件开头。下面给出一个完整的例子:

f = open("./tem/test2.txt", "w+", encoding='utf-8')
str2 = "1234569"
f.write(str2)
print("当前指针位置:"+str(f.tell()))#当前指针位置:7
f.seek(4)
f.write("aaa")
print("当前指针位置:"+str(f.tell()))#当前指针位置:7
f.close()
# 文件内容:1234aaa

f.close()

当你处理完一个文件后, 调用 f.close() 来关闭文件并释放系统的资源,如果尝试再调用该文件,则会抛出异常。

>>> f.close()
>>> f.read()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ValueError: I/O operation on closed file

当处理一个文件对象时, 使用 with 关键字是非常好的方式。在结束后, 它会帮你正确的关闭文件。 而且写起来也比 try - finally 语句块要简短:

with open("./tem/test.txt", "r+", encoding='utf-8') as f:
    print(f.readlines())

print(f.closed)#true

文件对象还有其他方法, 如 isatty() 和 trucate(), 但这些通常比较少用。

多文件拷贝案例

import multiprocessing
import os
import shutil


# 定义拷贝方法1
def copyFile(item, sourceDir, targetDir):
    try:
        f = open(os.path.join(sourceDir, item), "rb")
        w = open(os.path.join(targetDir, item), "wb")
        while True:
            read = f.read(1024)
            if read:
                w.write(read)
            else:
                f.close()
                w.flush()
                w.close()
                break
    except Exception as e:
        print(f"拷贝{item}出错:", e)


# 定义拷贝方法2:使用with关键字
def copyFile2(item, sourceDir, targetDir):
    try:
        with open(os.path.join(sourceDir, item), "rb") as f:
            with open(os.path.join(targetDir, item), "wb") as w:
                while True:
                    read = f.read(1024)
                    if read:
                        w.write(read)
                    else:
                        break
    except Exception as e:
        print(f"拷贝{item}出错:", e)


if __name__ == "__main__":
    # 1.定义源文件夹和目标文件夹
    sourceDir = r"D:\learn\AI产品经理\2、人工智能全套路线-北风网\1、数学基础(1)"
    targetDir = r"C:\Users\luzhanshi\Desktop\fileCopyTest"
    # 2.创建目标文件夹
    try:
        os.mkdir(targetDir)
    except FileExistsError:
        print("文件夹已存在,不需要创建")
    # 3.读取源文件文件列表
    listdir = os.listdir(sourceDir)
    # 4.使用多进程任务实现拷贝
    processes = []
    for item in listdir:
        process = multiprocessing.Process(target=copyFile2, args=(item, sourceDir, targetDir))
        process.start()
        print("开始拷贝:", item)
        processes.append(process)
    # 等待所有子进程完成:添加 process.join() 确保主进程等待所有子进程完成后再退出。
    for process in processes:
        process.join()
    print("拷贝完成!")

 

pickle 模块(序列化&反序列化)

python的pickle模块实现了基本的数据序列和反序列化。

通过pickle模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储。

通过pickle模块的反序列化操作,我们能够从文件中创建上一次程序保存的对象。

基本接口:

pickle.dump(obj, file, [,protocol])

有了 pickle 这个对象, 就能对 file 以读取的形式打开:

x = pickle.load(file)

注解:从 file 中读取一个字符串,并将它重构为原来的python对象。

file: 类文件对象,有read()和readline()接口。

# 序列化与反序列化
# 将对象写入文件
data={
    "list1":["one","two","three"],
    "set1":{1,2,3},
    "str":"一二三"
}
dict={"name":"TOM","age":18,"sex":1}
output = open("./tem/test3.txt", "wb")
pickle.dump(data,output)
pickle.dump(dict,output)
output.close()

# 读取文件内容
#使用pickle模块从文件中重构python对象
pkl_file = open('./tem/test3.txt', 'rb')
data = pickle.load(pkl_file)
print(data)#{'list1': ['one', 'two', 'three'], 'set1': {1, 2, 3}, 'str': '一二三'}
data2 = pickle.load(pkl_file)
print(data2)#{'age': 18, 'name': 'TOM', 'sex': 1}
pkl_file.close()

 

posted @ 2025-03-13 20:31  指尖下的世界  阅读(15)  评论(0)    收藏  举报