简介
大多数程序都需要从某处读取输入。本节将讨论文件访问。
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' ## 输出可能不同
>>>
首先,尝试一次性将整个文件作为一个大字符串读取:
>>> 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
语句。
既然你已经知道如何读取文件了,那我们来编写一个程序进行简单的计算。
portfolio.csv
中的列分别对应股票名称、股票持有数量以及单只股票的购买价格。在 /home/labex/project
目录下编写一个名为 pcost.py
的程序,该程序打开此文件,读取所有行,并计算购买投资组合中所有股票的总成本。
提示:要将字符串转换为整数,使用 int(s)
。要将字符串转换为浮点数,使用 float(s)
。
你的程序应输出如下内容:
Total cost 44671.15
如果你想读取一个非文本文件,比如一个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 这样的库已经有读取CSV文件的函数。这没错,而且效果相当不错。然而,这不是一门学习Pandas的课程。读取文件是一个比CSV文件的具体细节更具普遍性的问题。我们使用CSV文件的主要原因是,它是大多数程序员熟悉的格式,并且直接处理起来相对容易,在此过程中还能说明许多Python特性。所以,回去工作时你当然可以使用Pandas。不过在本课程的其余部分,我们将坚持使用标准的Python功能。
恭喜你!你已经完成了文件管理实验。你可以在LabEx中练习更多实验来提升你的技能。