哎呀,数据呢?存哪儿了?得给它拽出来啊!说白了,用 Python 怎么读取,不就是想把硬盘里、网上的、甚至别人输入的东西,变成我程序里能用的变量、能处理的字符嘛。这事儿吧,核心工具就是那个叫 open()
的家伙。就像你伸手去拿一个东西,得先“打开”它。
最常用的,读文本文件
这就像你看书,一个字一个字、一行一行地看。在 Python 里,读文本文件,你得用 open()
函数,并且指定模式。最常见的模式是 'r'
,那个 ‘r’ 就是 read 的缩写。
但记住,一定要用 with open(...) as f:
这个结构!答应我,好吗?别偷懒!因为它帮你处理善后,文件打开了,读完了,它会自动帮你关掉。不然,万一程序崩了,文件可能就一直开着,占资源,甚至被锁死。那感觉,糟透了。
“`python
示范一下,读个文本文件
try:
with open(‘my_precious_data.txt’, ‘r’, encoding=’utf-8′) as f:
# 接下来,你想怎么读就怎么读
content = f.read() # 一口气全读进来
print(“文件内容:\n”, content)
except FileNotFoundError:
print(“哎呀,文件没找到!看看路径对不对?”)
except Exception as e:
print(f”读取文件时出了点岔子:{e}”)
“`
看到没?with open(...) as f:
,然后指定文件名 'my_precious_data.txt'
,模式 'r'
。那个 encoding='utf-8'
简直是救星,后面我们单独聊聊这货!as f
就是把打开的文件对象取个名叫 f
,方便你操作。
三种主流的“读”姿势
打开文件后,怎么把里面的内容抓出来呢?主要有三种姿势,看你胃口大小和需求急缓:
-
f.read()
:一口气吞下去
想一口气把文件里所有内容都吞下去?用f.read()
。它会把整个文件内容作为一个巨大的字符串返回给你。python
with open('大文件警告.log', 'r', encoding='utf-8') as f:
all_text = f.read()
# 小心!文件太大,内存会哭给你看!
# print(all_text)
注意啊,要是文件特大,你内存可能就爆了。像个贪吃鬼,啥都往肚子里塞,但肚子(内存)是有限的。不到万不得已(确定文件小或者内存富裕),别这么干。不过读个配置文件、几k的小日志,这个方法最省事。 -
f.readline()
:一口一口品尝
或者你想一行一行地品味?就像喝茶,一口一口来。f.readline()
就是干这活儿的。每次调用,它就返回文件的一行(包括末尾的换行符\n
),直到文件末尾,返回一个空字符串''
。python
print("一行一行读:")
with open('log.txt', 'r', encoding='utf-8') as f:
line = f.readline()
while line:
print(f"读到一行: {line.strip()}") # strip() 去掉行尾的换行符
line = f.readline()
这个姿势处理日志文件、CSV 文件等,一行一个事件或一条记录,绝配!内存占用低,特别适合处理大文件。 -
f.readlines()
:把所有行打包成列表
想把所有行都变成一个列表?每行作为列表里的一项。f.readlines()
。python
print("\n把所有行放列表里:")
with open('config.ini', 'r', encoding='utf-8') as f:
lines_list = f.readlines()
# print(lines_list)
for i, line in enumerate(lines_list):
print(f"第 {i+1} 行: {line.strip()}")
这个也方便,特别是你需要对所有行进行迭代处理或者排序的时候。但同样,文件太大,这个列表也可能撑爆内存。它其实就是用readline()
循环读到文件尾,然后把读到的每一行扔进一个列表里。
更 Pythonic 的读行方式:直接迭代文件对象
其实啊,读行还有一个更酷、更简洁的方式,就是直接遍历文件对象 f
本身!
python
print("\n最优雅的读行方式:")
with open('another_log.txt', 'r', encoding='utf-8') as f:
for line in f:
print(f"又读到一行: {line.strip()}")
这个 for line in f:
的方式,在后台其实也是一行一行地读,效率高,代码简洁,是处理大文件时读行的首选,强烈推荐!
那个让人抓狂的“编码”问题 (Encoding)
前面提到的 encoding='utf-8'
,这事儿太重要了!读文本文件,如果文件保存时的编码和你的程序打开时指定的编码不一致,恭喜你,一堆乱码甚至 UnicodeDecodeError
正在向你招手。那堆看不懂的字符蹦出来的时候,是不是想砸电脑?
UnicodeDecodeError
,多么“亲切”的错误信息啊!它告诉你,“哥们,我用你指定的编码(比如默认的 ASCII,或者你指定的 UTF-8)去理解文件里的字节流,发现它们根本不符合这个编码的规范!”
为了避免这个,务必在 open()
里加上 encoding='utf-8'
。现在基本上全世界的网页、新创建的文本文件都倾向于用 UTF-8 了,它能表示几乎所有语言的字符,统一战线,方便你我。
当然,遇到那种古老的、从 Windows XP 时代传下来的 txt 文件,它可能用的是 GBK、GB2312 甚至 Latin-1。那时候,你就得根据文件的实际编码来指定了,比如 encoding='gbk'
。怎么知道文件的编码?有时候是玄学,得靠经验、靠文本编辑器(比如 VS Code、Notepad++ 都能识别)或者专门的编码检测库(比如 chardet
)来猜。猜对了皆大欢喜,猜错了?嘿嘿,乱码继续陪你玩。
读非文本文件:二进制模式 ('rb'
)
好了,不是所有文件都是文本。图片 (.jpg, .png)、音频 (.mp3)、视频 (.mp4)、压缩包 (.zip, .gz)、还有 Python 里用 pickle
序列化保存的对象… 这些都是二进制文件。它们不是由人类可读的字符组成的,而是一堆字节 (bytes)。
读这些文件,模式就得换成 'rb'
。那个 ‘b’ 就是 binary 的意思。
“`python
读个图片文件试试
try:
with open(‘my_image.jpg’, ‘rb’) as f:
binary_data = f.read() # 读到的是 bytes 类型的数据
print(f”读取了 {len(binary_data)} 个字节的图片数据。类型是: {type(binary_data)}”)
# print(binary_data[:20]) # 打印前20个字节看看
# 你不能直接 print 二进制数据,它不是字符串!
# 通常你会用特定的库来处理这些 bytes,比如 PIL 处理图片,pickle 加载对象
except FileNotFoundError:
print(“图片文件没找到!”)
``
‘rb’
在模式下,
f.read()返回的是
bytes对象,而不是
str。
f.readline()和
f.readlines()也能用,但它们返回的是以换行符(在二进制里就是特定的字节序列)分割的
bytes` 行。处理二进制数据,感觉就像在处理最原始的积木块,没啥字符格式可言,就是一堆数字(0-255)。处理图片库、网络通信、文件复制啥的,这个模式少不了。
别忘了错误处理 (Error Handling)
我们前面已经零星地提到了,但值得单独强调:读取文件这事儿,外部因素太多了!文件可能不存在、路径错了、你没权限读、文件被别人占用了… 任何一步都可能出错。
所以啊,用 try...except
把你的文件读取代码包起来,是个好习惯,不,是个必须养成的习惯!
“`python
file_path = ‘maybe_exists.txt’
try:
with open(file_path, ‘r’, encoding=’utf-8′) as f:
content = f.read()
print(f”成功读取文件 {file_path}:\n{content}”)
except FileNotFoundError:
print(f”惨了!要读的文件 ‘{file_path}’ 不存在啊!”)
except PermissionError:
print(f”没权限!'{file_path}’ 文件不让我读!”)
except UnicodeDecodeError:
print(f”编码问题!文件 ‘{file_path}’ 不是 UTF-8 编码,试试别的编码?”)
except Exception as e:
print(f”读取文件 ‘{file_path}’ 时发生未知错误: {e}”)
“`
这样,就算文件出问题,你的程序也不会直接崩掉,而是会给用户一个友好的提示,或者至少不会卡死在那里。
还有别的方式“读”吗?
除了从文件系统读,Python 还能从别的地方“读”数据啊!
-
标准输入 (Standard Input): 就是用户在命令行里敲的东西。
input()
函数大家都熟,它就是从标准输入里读一行字符串。想读更复杂的?sys.stdin
,不过那个用得可能少点,除非你在写特别底层的命令行工具。 -
网络连接 (Network Connections): 通过 socket 或者各种库(如
requests
),你可以从网络上“读取”数据流。这跟读文件有点像,也是一串字节流,但源头是网络。 -
内存中的字符串 (In-memory Strings): 你甚至可以把一个字符串当成文件来读!
io.StringIO
和io.BytesIO
这两个类就能干这事儿。当你有些文本或字节数据已经在内存里了,但你又想用文件对象那样的方法(比如.read()
,.readline()
)去处理它,它们就派上用场了。
“`python
把字符串当文件读
import io
string_data = “第一行文本\n第二行。\n第三行就这么结束了。”
string_io = io.StringIO(string_data)
print(“\n从内存字符串读:”)
print(string_io.readline().strip())
print(string_io.read()) # 从当前位置读到尾
“`
你看,Python 怎么读取 这事儿,看着简单一个 open()
,里面弯弯绕绕还不少呢。模式、编码、读取方式、异常处理、还有那个救命的 with
语句。每一个环节都可能藏着 bug,尤其是编码,绝对是新手的老大难。但掌握了这些,你就能轻松地把外部世界的数据‘吸’进你的程序里,让它们活起来。就像给你的程序装上了眼睛和耳朵,能感知外面的信息了。是不是挺酷的?多练练,找几个不同格式的文件试试,感觉就来了。别怕踩坑,踩着踩着,你就知道哪儿有坑,怎么绕过去了。