美文网首页Python基础知识
我要悄悄学Python之文件与异常(二)

我要悄悄学Python之文件与异常(二)

作者: 小志Codings | 来源:发表于2021-04-17 14:50 被阅读0次

    交心的不一定是真朋友。

    遇到问题嘴上站在你身边和真正站在你身边,完全是两码事。

    和别人起冲突时,沉默不语,事后才骂对方的朋友没必要深交;

    会帮你道歉,但一旦你受到欺负,就为你出头的朋友,才是真的铁。

    文件与异常(二)

    在本篇专题中你可以学到:

    • 读取和写入文本文件
    • 处理数据集合
    • 处理命令行参数
    • 抛出和处理异常

    迭代文件中的行

    你已经知道了怎么样一次读取文件中的一行。然而,有更简单的方法。Python可以像处理每行是一个字符串的字符串容器那样对待一个输入文件。为了从文件中读取文本行,你可以使用for循环迭代文件对象。

    infile = open('input.txt', 'r')
    for line in infile:
        print(line)
    infile.close()
    

    在每个迭代的开始,循环变量line被赋值为包含文件中下一行文本的一个字符串。在循环体内部,你简单的处理文本即可。

    然而,文件和容器之间有个关键区别。一旦文件被读取,你就不能再次迭代这个文件,除非先关闭文件并再次打开。

    print函数的结尾是以换行符结束的,文件中的每一行的末尾也是一个换行符,因此,当我们的文件中包含一系列单词的输入文件,每行一个单词:

    flask
    django
    python
    

    在输入文件的行被输出到终端时,它们会被显示成每个单词之间有个空行:

    flask
    
    django
    
    python
    

    一般地,在使用输入字符串之前必须删除换行符。第一个文本行被读入时,字符串行的末尾是包含着换行符的:flask\n

    为了删除换行符,对字符串应用rstrip方法:

    line = line.rstrip()
    

    从而得到新的字符串:flask

    利用rstrip方法创建一个新的字符串,删除原字符串尾部的所有空白字符(空格、制表符、换行符)。例如,如果第三个文本行的单词python后面

    跟着两个空格:python \n

    rstrip方法会同时删除两个空格和换行符:python

    为了删除字符串尾部的指定字符,你可以把包含那些字符的字符串参数传递给rstrip方法。例如,我想要删除字符串尾部的一个圆点或一个问号,可以使用命令:

    line = line.rstrip('.?')
    

    下面的表格将更加细致的展示出rstrip的使用方法。

    方法 返回值
    s.lstrip()<br />s.lstrip(chars) 字符串s的新版本,其中s的左侧是空白字符(空格、制表符、换行符)都被删除。如果提供了参数chars,那么字符串chars中的字符都被删除,而不删除空白字符
    s.rstrip()<br />s.strip(chars) 字符串s的新版本,其中s的右侧是空白字符(空格、制表符、换行符)都被删除。如果提供了参数chars,那么字符串chars中的字符都被删除,而不删除空白字符
    s.strip()<br />s.strip(chars) 类似于lstriprstrip,只是在s的两侧删除字符

    读取单词

    有时候,你可能需要从一个文件中读取独立的单词。例如,假设我们的输入文件包含两行文本:

    Mary had a little lamb,
    whose fleece was white as snow.
    

    我想把这些单词输出到终端,每行一个单词。

    到目前为止,我想没有从一个文件中读取一个单词的方法,你必须首先读取一行,然后将其切分成独立的单元,这可以使用split方法完成。

    worldList = line.split()
    

    这里的split方法返回在每个空白字符处,对原始字符串进行切分得到子字符串的列表。

    具体代码如下所示:

    infile = open('word.txt', 'r')
    for line in infile:
        line = line.strip('.,\n')
        words = line.split()
        for word in words:
            print(word)
    infile.close()
    

    默认地,split方法使用空白字符作为分隔符。你也可以不同的分隔符切分为字符串。假如,单词之间使用冒号分隔,而不是空白符。

    line = 'apples:pears:oranges:grapes'
    substring = line.split(':')
    

    上面的代码会将字符串切分成4个子字符串:

    "apples" "pears" "oranges" "grapes"
    

    注意,如果传递了分隔符作为参数,连续的分隔符不会被当作一个来处理,就像是没有提供参数一样。

    line = 'apples:pears:oranges::grapes'
    substring = line.split(':')
    

    这样将会被分隔成5个子字符串:

    "apples" "pears" "oranges" " " "grapes"
    

    其中一个是空白字符。

    下表将提供更加详细的split方法

    方法 返回值
    s.split()<br />s.split(sep)<br />s.split(sep, maxsplit) 从字符串s返回一个单词列表。如果提供了字符串sep,它被当作分隔符使用;否则,任何空白字符都会被当作分隔符。如果提供了maxsplit,就只分隔多次,得到最多maxsplit+1个单词
    s.rstrip(sep, maxsplit) split一样,只不过这是从尾部开始分隔,而不是从前面开始
    s.splitline() 返回一个字符串中独立行组成的列表,使用换行符\n作为分隔符

    读取字符

    你可以使用read方法读取独立的字符,而不是读取一整行,read方法接收一个参数,用来指定要读取的字符数量。这个方法返回包含读取的字符的字符串,使用1作为参数时:

    char = inputfile.read(1)
    

    read方法返回包含文件中下一个字符串。或者,已经达到文件尾部就返回空字符串" "。下面的循环处理文件中的内容,每次一个字符:

    inputfile = open('字符.txt', 'r')
    char = inputfile.read(1)
    while char != '':
        print(char)
        char = inputfile.read(1)
    inputfile.close()
    
    inputfile = open('字符.txt', 'r')
    char = inputfile.read(1)
    while char != '':
        print(char, end='')
        char = inputfile.read(1)
    inputfile.close()
    

    有换行效果与没有换行效果能够让你更加容易理解这段代码。

    注意:read方法会读取和返回换行符,遇到它们时就结束当前行。

    让我们写一个简单的程序,来计算文件中英语字母出现的次数。因为我们要维护计数的字母有26个,因此,我们可以使用一个包含26个用整数表示的计数器列表。

    letterCounts = [0] * 26
    

    字母"A"由counts[0]来维护,字母"B"由counts[1]来维护,以此类推,使用counts[25]来表示字母"Z"出现的次数。

    我们不使用复杂的选择语句,可以使用ord函数来返回每个字符串的Unicode值。大写字母是按顺序编码的,从字母A的65到字母Z的90,把得到的值减去字母A的编码得到介于0至25之间的值,将其作为letterCounts列表的索引。

    code = ord(char) - ord('A')
    letterCounts = letterCounts[code] + 1
    

    注意,所有小写字母在做统计之前都需要将其转换为大写字母。

    letterCount = [0] * 26
    inputfile = open('统计.txt', 'r')
    char = inputfile.read(1)
    while char != '':
        char = char.upper()
        if char >= 'A' and char <= 'Z':
            code = ord(char) - ord('A')
            letterCount[code] = letterCount[code] + 1
            char = inputfile.read(1)
    print(letterCount)
    inputfile.close()
    

    注意:你所要统计的字符不能出现有任何的空格、换行与标点符号,否则将会进入死循环。因此,这段代码的bug还是比较多的,留给你们的任务是将这段代码的bug修复。

    读取记录

    一个文本文件可以包含数据记录的集合,每个记录中包含多个字段。例如,一个包含学生数据的文件可能包含身份证号、完整名字和年纪这些字段组成的记录。一个包含银行账号交易的文件可能包含由交易日期、描述和金额这些字段组成的记录。

    比如下面的数据,每个记录包含两个字段:国家名字及人口。这样的数据的经典格式是每个字段存储为文件的一行,单个记录的所有字段连续存储:

    China
    1330044605
    India
    1147995898
    Unite States
    303824646
    

    读取这样格式的数据是非常容易的。因为每个记录包含两个字段,我们从文件中读取两行来构成一个记录。这时我们可以使用readline方法和一个检查文件尾部(警戒值)的while循环:

    infile = open('国家人口.txt', 'r')
    line = infile.readline()
    while line !='':
        countryName = line.rstrip()
        line = infile.readline()
        population = int(line)
        print('%s:%d' % (countryName, population))
        line = infile.readline()
    infile.close()
    

    输出结果,如下所示:

    China:1330044605
    India:1147995898
    Unite States:303824646
    

    文件处理实战

    我们使用下面的程序来处理一段含文本和数字的数据记录

    ##
    # 该程序读取一个文件,其中的行包含项目和价格,就像:
    # item name 1:price1
    # item name 2:price2
    # 每个项目的名字以冒号结束。
    # 该程序写入一个文件,其中项目左对齐而价格右对齐
    # 最后一行是价格总和
    
    # 提示输入文件和输出文件的名字
    inputFileName = input('Input file: ')
    outputFileName = input('Output file: ')
    
    # 打开输入文件和输出文件
    # 为了避免编码错误,可能需要设置encoding
    inputFile = open(inputFileName, 'r', encoding='utf-8')
    outputFile = open(outputFileName, 'w', encoding='utf-8')
    
    # 读取输入并写入输出
    total = 0.0
    
    for line in inputFile:
        # 在冒号处切分记录
        print(line)
        parts = line.split(':')
    
        # 提取两个数据段
        item = parts[0]
        price = float(parts[1])
    
        # 增加total
        total += price
    
        # 写入输出
        outputFile.write('%-20s%10.2f\n' % (item, price))
    
    # 写入价格总和
    outputFile.write('%-20s%10.2f\n' % ('Total:', total))
    
    
    # 关闭文件
    inputFile.close()
    outputFile.close()
    
    # 成功提醒
    print('处理完毕')
    

    最后

    迷茫不仅阻挡前方的去路,还让我们看不清未来的方向,使得我们越发焦虑,生活越发低沉......

    面对每一次的失败,我们要相信:

    这不是结束,甚至不是结束的开始,而是开始的结束

    看完觉得有收获的,可以给啃书君点个【在看】,愿我们都能勇往直前,找到适合自己的道路。

    我是啃书君,一个专注于学习的人,你懂的越多,你不懂的越多,更多精彩内容,我们下期再见!

    相关文章

      网友评论

        本文标题:我要悄悄学Python之文件与异常(二)

        本文链接:https://www.haomeiwen.com/subject/scnulltx.html