文件访问基础

PythonPythonBeginner
立即练习

This tutorial is from open-source community. Access the source code

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

大多数程序都需要从某处读取输入。本节将讨论文件访问。

文件输入与输出

打开一个文件。

f = open('foo.txt', 'rt')     ## 以读取模式(文本)打开
g = open('bar.txt', 'wt')     ## 以写入模式(文本)打开

读取所有数据。

data = f.read()

## 最多读取'maxbytes' 字节的数据
data = f.read([maxbytes])

写入一些文本。

g.write('some text')

完成后关闭文件。

f.close()
g.close()

文件应该正确关闭,但这很容易被遗忘。因此,推荐的方法是像这样使用 with 语句。

with open(filename, 'rt') as file:
    ## 使用文件 `file`
  ...
    ## 无需显式关闭
...语句

当控制离开缩进的代码块时,这会自动关闭文件。

读取文件数据的常见用法

一次性将整个文件作为字符串读取。

with open('foo.txt', 'rt') as file:
    data = file.read()
    ## `data` 是一个包含 `foo.txt` 中所有文本的字符串

通过迭代逐行读取文件。

with open(filename, 'rt') as file:
    for line in file:
        ## 处理该行

写入文件的常见用法

写入字符串数据。

with open('outfile', 'wt') as out:
    out.write('Hello World\n')
 ...

重定向 print 函数。

with open('outfile', 'wt') as out:
    print('Hello World', file=out)
 ...

这些练习依赖于一个名为 portfolio.csv 的文件。该文件包含一系列行,每行都有关于一个股票投资组合的信息。假设你在 ~/project/ 目录下工作。如果你不确定,可以通过以下方式查看 Python 认为它正在运行的位置:

>>> import os
>>> os.getcwd()
'/home/labex/project' ## 输出可能不同
>>>

练习1.26:文件基础操作

首先,尝试一次性将整个文件作为一个大字符串读取:

>>> with open('portfolio.csv', 'rt') as f:
        data = f.read()

>>> data
'name,shares,price\n"AA",100,32.20\n"IBM",50,91.10\n"CAT",150,83.44\n"MSFT",200,51.23\n"GE",95,40.37\n"MSFT",50,65.10\n"IBM",100,70.44\n'
>>> print(data)
name,shares,price
"AA",100,32.20
"IBM",50,91.10
"CAT",150,83.44
"MSFT",200,51.23
"GE",95,40.37
"MSFT",50,65.10
"IBM",100,70.44
>>>

在上述示例中,需要注意的是Python有两种输出模式。在第一种模式下,当你在提示符处输入 data 时,Python会向你展示原始字符串表示形式,包括引号和转义码。当你输入 print(data) 时,你会得到字符串的实际格式化输出。

虽然一次性读取整个文件很简单,但这通常不是最合适的方法 —— 特别是当文件非常大或者包含你想要一次处理一行的文本行时。

要逐行读取文件,可以使用如下的 for 循环:

>>> with open('portfolio.csv', 'rt') as f:
        for line in f:
            print(line, end='')

name,shares,price
"AA",100,32.20
"IBM",50,91.10
...
>>>

当你像这样使用这段代码时,行会一直被读取,直到到达文件末尾,此时循环停止。

在某些情况下,你可能想要手动读取或跳过 一行 文本(例如,也许你想要跳过第一行的列标题)。

>>> f = open('portfolio.csv', 'rt')
>>> headers = next(f)
>>> headers
'name,shares,price\n'
>>> for line in f:
    print(line, end='')

"AA",100,32.20
"IBM",50,91.10
...
>>> f.close()
>>>

next() 会返回文件中的下一行文本。如果你重复调用它,你会得到连续的行。不过,要知道,for 循环已经在使用 next() 来获取其数据了。因此,通常你不会直接调用它,除非你像这样试图明确地跳过或读取一行。

一旦你开始读取文件的行,你就可以开始进行更多的处理,比如分割。例如,试试这个:

>>> f = open('portfolio.csv', 'rt')
>>> headers = next(f).split(',')
>>> headers
['name','shares', 'price\n']
>>> for line in f:
    row = line.split(',')
    print(row)

['"AA"', '100', '32.20\n']
['"IBM"', '50', '91.10\n']
...
>>> f.close()

注意:在这些示例中,显式调用了 f.close(),因为没有使用 with 语句。

练习1.27:读取数据文件

既然你已经知道如何读取文件了,那我们来编写一个程序进行简单的计算。

portfolio.csv 中的列分别对应股票名称、股票持有数量以及单只股票的购买价格。在 /home/labex/project 目录下编写一个名为 pcost.py 的程序,该程序打开此文件,读取所有行,并计算购买投资组合中所有股票的总成本。

提示:要将字符串转换为整数,使用 int(s)。要将字符串转换为浮点数,使用 float(s)

你的程序应输出如下内容:

Total cost 44671.15
✨ 查看解决方案并练习

练习1.28:其他类型的“文件”

如果你想读取一个非文本文件,比如一个gzip压缩的数据文件,该怎么办呢?内置的 open() 函数在这里帮不了你,但Python有一个库模块 gzip,它可以读取gzip压缩文件。

试试看:

>>> import gzip
>>> with gzip.open('portfolio.csv.gz', 'rt') as f:
    for line in f:
        print(line, end='')

... 查看输出结果...
>>>

注意:这里包含 'rt' 文件模式至关重要。如果你忘了这一点,你得到的将是字节串而不是普通的文本字符串。

评论:我们难道不应该用Pandas来做这个吗?

数据科学家们很快指出,像 Pandas 这样的库已经有读取CSV文件的函数。这没错,而且效果相当不错。然而,这不是一门学习Pandas的课程。读取文件是一个比CSV文件的具体细节更具普遍性的问题。我们使用CSV文件的主要原因是,它是大多数程序员熟悉的格式,并且直接处理起来相对容易,在此过程中还能说明许多Python特性。所以,回去工作时你当然可以使用Pandas。不过在本课程的其余部分,我们将坚持使用标准的Python功能。

总结

恭喜你!你已经完成了文件管理实验。你可以在LabEx中练习更多实验来提升你的技能。