本文概述
作为数据科学家, 你一定会处理大量数据!你将从多个来源, 数据库, Excel, 平面文件接收此数据。你将需要知道如何在平面文件中打开, 读取和写入数据, 以便可以对它们进行分析。
这正是本教程将介绍的内容!你将了解:
- Python文件对象;
- 如何打开文件, 以便可以访问数据;
- 如何从文件中读取数据;
- 访问数据后, 你也可以关闭文件
- 并且还将数据写入文件;
- 你还将看到一些Python文件对象属性,
- 并看看File对象的其他方法
- 最后, 你将深入研究Python os模块。
提示:如果你想了解有关在Python中导入文件的更多信息, 请查看srcmini的”在Python中导入数据”课程。
平面文件与文本文件
首先, 你首先应该知道什么是平面文件以及它们与文本文件的区别。
平面文件是包含记录的数据文件, 这些记录在记录之间没有结构化的关系, 也没有索引的结构, 就像你通常在关系数据库中找到它一样。这些文件只能包含基本格式, 具有固定的少量字段, 并且可以具有文件格式, 也可以不具有文件格式。
平面文件可以是纯文本文件或二进制文件。在前一种情况下, 文件通常每行包含一个记录:
- 逗号分隔值(CSV)文件, 其中包含用分隔的数据值, 例如:
名称, 地址, 电子邮件ABC, 城市A, abc @ xyz.com LMN, 城市B, lmn @ xyz.com PQR, 城市C, pqr @ xyz.com - 带分隔符的文件, 其中包含带有用户指定的分隔符的数据值。这可以是\ t标签或符号(#, &, ||), 例如:
名称||地址||电子邮件ABC ||城市A||abc@xyz.com LMN ||城市B||lmn@xyz.com PQR ||城市C||pqr@xyz.com
但这对Python意味着什么?
Python文件对象
Python具有内置功能来创建和操作文件。 io模块是用于访问文件的默认模块, 你无需导入它。该模块由open(filename, access_mode)返回, 该文件返回一个文件对象, 该文件对象称为”句柄”。你可以使用此句柄读取或写入文件。 Python将文件视为对象, 它具有自己的属性和方法。
如前所述, 平面文件有两种类型:文本文件和二进制文件:
- 正如你阅读上一节所期望的那样, 文本文件具有行尾(EOL)字符以指示每行的终止。在Python中, 换行符(\ n)是默认的EOL终止符。
- 由于二进制文件在将数据转换为二进制语言(0和1)之后存储数据, 因此没有EOL字符。此文件类型返回字节。这是处理非文本文件(例如图像或exe)时要使用的文件。
在本教程中, 你将更多地关注文本文件。
打开()
内置的Python函数open()具有以下参数:
`open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)`
上面的open()还会告诉每个参数的默认值。首先, 让我们动手操作使用前两个参数open(文件, 模式)读取和写入文件, 并逐个浏览其他参数。
注意, 在本教程中, 将不讨论opener, 因为它用于低级I / O操作。
文件
file是必须提供给open函数的参数。所有其他参数都是可选的, 并且具有默认值。现在, 此参数基本上是文件所在的路径。
如果路径在当前工作目录中, 则可以提供文件名, 如以下示例所示:
my_file_handle=open("mynewtextfile.txt")
如果文件位于该目录之外的目录中, 则必须提供具有文件名的完整路径:
my_file_handle=open("D:\\new_dir\\anotherfile.txt")
my_file_handle.read()
'Hi, \nI am in D Drive srcmini folder'
确保给定的文件名和路径正确, 否则会出现FileNotFoundError:
my_file_handle=open("D:\\new_dir1\\anotherfile.txt")
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
<ipython-input-3-f10ef385d072> in <module>()
----> 1 my_file_handle=open("D:\\new_dir1\\anotherfile.txt")
FileNotFoundError: [Errno 2] No such file or directory: 'D:\\new_dir1\\anotherfile.txt'
你可以使用try-finally块捕获异常:
try:
my_file_handle=open("D:\\new_dir1\\anotherfile.txt")
except IOError:
print("File not found or path is incorrect")
finally:
print("exit")
存取模式
访问模式定义打开文件, 打开文件以只读, 只写或二者兼有的方式。它指定你要从哪个位置开始读取或写入文件。
你可以通过mode参数指定文件的访问模式。你使用默认模式” r”来读取文件。在其他要编写或附加的情况下, 分别使用” w”或” a”。
当然, 还有更多的访问模式!看一下下表:
字符 | 函数 |
---|---|
[R | 打开文件仅供读取。从文件开头开始读取。此默认模式。 |
rb | 打开一个文件, 仅以二进制格式读取。从文件开头开始读取。 |
r+ | 打开文件进行读写。文件指针放置在文件的开头。 |
在 | 打开文件仅用于写入。文件指针放置在文件的开头。覆盖现有文件, 如果不存在则创建一个新文件。 |
wb | 与w相同, 但以二进制模式打开。 |
w+ | 与w相同, 但也允许从文件读取。 |
wb + | 与wb相同, 但也允许从文件读取。 |
一个 | 打开一个文件进行追加。在文件末尾开始写入。如果文件不存在, 则创建一个新文件。 |
ab | 与a相同, 但采用二进制格式。如果文件不存在, 则创建一个新文件。 |
a+ | 一样, 但也可以阅读。 |
从+ | 相同的ab, 但也可以阅读。 |
正如你在第一部分中所看到的, 平面文件有两种类型, 这也是为什么还有一个选项可以指定要以哪种格式打开文件, 例如文本或二进制。当然, 前者是默认设置。
从文件读取
让我们尝试所有从文件读取的读取方法, 你还将一起探索访问模式!有三种读取文件的方法。
- 读([n])
- readline([n])
- readlines()
注意:n是要读取的字节数。
创建如下文件:
1st line
2nd line
3rd line
4rth line
5th line
让我们看看每种读取方法的作用:
my_file=open("D:\\new_dir\\multiplelines.txt", "r")
my_file.read()
如果未在参数中给出字节数, 则read()方法仅输出整个文件。如果执行my_file.read(3), 你将获取文件的前三个字符
my_file=open("D:\\new_dir\\multiplelines.txt", "r")
my_file.read(3)
readline(n)输出文件单行最多n个字节。它读取的内容不超过一行。
my_file.close()
my_file=open("D:\\new_dir\\multiplelines.txt", "r")
#Use print to print the line else will remain in buffer and replaced by next statement
print(my_file.readline())
# outputs first two characters of next line
print(my_file.readline(2))
使用close()关闭Python文件
将close()方法与文件句柄一起使用以关闭文件。使用此方法时, 请清除所有缓冲区并关闭文件。
my_file.close()
你可以使用for循环逐行读取文件:
my_file=open("D:\\new_dir\\multiplelines.txt", "r")
#Use print to print the line else will remain in buffer and replaced by next statement
for line in my_file:
print(line)
my_file.close()
readlines()方法维护文件中每行的列表:
my_file=open("D:\\new_dir\\multiplelines.txt", "r")
my_file.readlines()
写入文件
你可以使用以下三种方法在Python中写入文件:
- write(string)(用于文本)或write(byte_string)(用于二进制)
- 文字行(列表)
让我们在” D”驱动器的文件夹内创建一个新文件。以下操作将在指定的文件夹中创建一个新文件, 因为该文件不存在。请记住使用正确的文件名提供正确的路径, 否则会出现错误:
创建一个记事本文件, 并在其中写入一些文本。确保将文件另存为.txt并将其保存到Python的工作目录中。
my_file_handle=open("mynewtextfile.txt")
my_file_handle.read()
new_file=open("D:\\new_dir\\newfile.txt", mode="w", encoding="utf-8")
new_file.write("Writing to a new file\n")
new_file.write("Writing to a new file\n")
new_file.write("Writing to a new file\n")
new_file.close()
现在, 让我们使用a +模式将此文件写入列表:
fruits=["Orange\n", "Banana\n", "Apple\n"]
new_file=open("D:\\new_dir\\newfile.txt", mode="a+", encoding="utf-8")
new_file.writelines(fruits)
for line in new_file:
print(line)
new_file.close()
请注意, 从文件读取不会打印任何内容, 因为文件光标位于文件的末尾。要在开始处设置光标, 可以使用文件对象的seek()方法:
cars=["Audi\n", "Bentely\n", "Toyota\n"]
new_file=open("D:\\new_dir\\newfile.txt", mode="a+", encoding="utf-8")
for car in cars:
new_file.write(car)
print("Tell the byte at which the file cursor is:", new_file.tell())
new_file.seek(0)
for line in new_file:
print(line)
文件对象的tell()方法告诉文件光标位于哪个字节。在seek(offset, reference_point)中, 参考点是0(文件的开头, 并且是默认值), 1(文件的当前位置)和2(文件的结尾)。
让我们尝试传递另一个参考点和偏移量, 然后查看输出:
new_file.seek(4, 0)
print(new_file.readline())
new_file.close()
请注意.seek()和.truncate()的使用:.truncate()中的参数为5, 表示将文件截断直到剩下5个字节的文本。输出显示正好剩下5个字节的文本, 包括空格。你只剩下next()方法, 因此让我们完成本节教程!在这里, 你使用的是上面创建的相同文件, 名称为multiplelines.txt。
如果文件模式不包括” b”(表示二进制格式), 则不允许使用诸如seek(-2, 2)之类的相对结束搜索。当将文件对象作为文本文件处理时, 仅允许诸如seek(0, 2)之类的转发操作。
file=open("D:\\new_dir\\multiplelines.txt", "r")
for index in range(5):
line=next(file)
print(line)
file.close()
请注意, write()实际上不会将数据写入文件, 但实际上会将数据写入缓冲区, 而是仅在调用close()时才写入。后一种方法刷新缓冲区并将内容写入文件。如果你不想关闭文件, 请使用fileObject.flush()方法清除缓冲区并写回文件。
你也可以将数据写入.json文件。
切记:Javascript Object Notation(JSON)已成为流行的方法, 可通过网络交换结构化信息并在平台之间共享信息。它基本上是具有某种结构的文本, 并将其保存为.json会告诉你如何读取结构, 否则它只是纯文本文件。它将数据存储为key:value对。结构可以简单到复杂。
看看以下针对国家及其首都的简单JSON:
{
"Algeria":"Algiers", "Andorra":"Andorra la Vella", "Nepal":"Kathmandu", "Netherlands":"Amsterdam", }
:之前的任何内容都称为键, 而:之后的任何内容均称为值。这与Python字典非常相似, 不是吗!你可以看到数据由分隔, 并且花括号定义了对象。方括号用于在更复杂的JSON文件中定义数组, 如以下摘录所示:
{
"colors": [
{
"color": "black", "category": "hue", "type": "primary", "code": {
"rgba": [255, 255, 255, 1], "hex": "#000"
}
}, {
"color": "white", "category": "value", "code": {
"rgba": [0, 0, 0, 1], "hex": "#FFF"
}
}, {
"color": "red", "category": "hue", "type": "primary", "code": {
"rgba": [255, 0, 0, 1], "hex": "#FF0"
}
}, {
"color": "blue", "category": "hue", "type": "primary", "code": {
"rgba": [0, 0, 255, 1], "hex": "#00F"
}
}, {
"color": "yellow", "category": "hue", "type": "primary", "code": {
"rgba": [255, 255, 0, 1], "hex": "#FF0"
}
}, {
"color": "green", "category": "hue", "type": "secondary", "code": {
"rgba": [0, 255, 0, 1], "hex": "#0F0"
}
}, ]
}
请注意, JSON文件也可以在一个对象中保存不同的数据类型!
使用read()读取文件时, 将从文件中读取字符串。这意味着在读取数字时, 需要使用int()这样的数据类型转换函数将它们转换为整数。对于更复杂的用例, 你始终可以使用json模块。
如果有一个对象x, 则可以用简单的代码行查看其JSON字符串表示形式:
# Importing json module
import json
my_data=["Hafsa Jabeen", "Reading and writing files in python", 78546]
json.dumps(my_data)
要将JSON写入文件中, 可以使用.dump()方法:
with open("jsonfile.json", "w") as f:
json.dump(my_data, f)
f.close()
注意:最好使用with-open方法打开文件, 因为如果在途中出现任何异常, 它将正确关闭文件。这是尝试最终块的好选择。
已完成文件创建, 并已加载json包。如果打开了一个JSON文件以供读取, 则可以使用load(file)对其进行解码, 如下所示:
with open("jsonfile.json", "r") as f:
jsondata=json.load(f)
print(jsondata)
f.close()
同样, 可以使用json模块存储更复杂的字典。你可以在这里找到更多信息。
现在, 你将看到open()方法的其他一些参数, 在上一节中已经看到了。让我们从缓冲开始。
缓冲
缓冲区保留来自操作系统文件流的大量数据, 直到使用它来输入更多数据为止, 这类似于视频缓冲。
当你不知道正在使用的文件大小时, 缓冲很有用;如果文件大小大于计算机内存, 则处理单元将无法正常工作。缓冲区大小告诉你一次使用之前可以保留多少数据。io.DEFAULT_BUFFER_SIZE可以告诉你平台的默认缓冲区大小。
(可选)你可以将整数传递给缓冲以设置缓冲策略:
- 0以关闭缓冲(仅在二进制模式下允许)
- 1选择行缓冲(仅在文本模式下可用)
- 任何大于1的整数, 以指示固定大小的块缓冲区的字节大小
- 使用负值将缓冲策略设置为系统默认值
如果你未指定任何政策, 则默认值为:
- 二进制文件以固定大小的块缓冲
- 选择缓冲区的大小取决于底层设备的”块大小”。在许多系统上, 缓冲区的长度通常为4096或8192字节。
- “交互式”文本文件(isatty()返回True的文件)使用行缓冲。其他文本文件将上述策略用于二进制文件。请注意, isatty()可用于查看你是否已连接到类似Tele-TYpewriter()的设备。
import io
print("Default buffer size:", io.DEFAULT_BUFFER_SIZE)
file=open("mynewtextfile.txt", mode="r", buffering=5)
print(file.line_buffering)
file_contents=file.buffer
for line in file_contents:
print(line)
请注意, 如果你按open(file, mode =’r’, buffering = -1, encoding = None, errors = None, newline = None, closefd = True, opener = None)中指定的顺序使用所有参数, 你无需编写参数名称!如果由于要保留默认值而跳过参数, 则最好将所有内容全部写完整。
错误
一个可选的字符串, 指定如何处理编码和解码错误。该参数不能在二进制模式下使用。可以使用多种标准错误处理程序(在”错误处理程序”下列出)。
file=open("mynewtextfile.txt", mode="r", errors="strict")
print(file.read())
file.close()
如果存在编码错误, errors =” strict”引发ValueErrorException。
新队
newline控制通用换行模式的工作方式(仅适用于文本模式)。可以是”无”, “”, ” \ n”, ” \ r”和” \ r \ n”。在上面的示例中, 你看到将None传递给换行符会将’\ r \ n’转换为’\ n’。
- 无:启用通用换行模式。输入中的行可以以’\ n’, ‘\ r’或’\ r \ n’结尾, 并将它们转换为默认的行分隔符
- “”:启用通用换行模式, 但不翻译返回行尾
- ‘\ n’, ‘\ r’, ‘\ r \ n’:输入行仅由给定的字符串终止, 并且行尾不进行翻译。
请注意, 通用换行符是一种解释文本流的方式, 其中, 以下所有字符均被视为结束行:Unix行尾约定’\ n’, Windows约定’\ r \ n’和旧的Macintosh约定’\ r’。
还要注意, os.linesep返回系统的默认行分隔符:
file=open("mynewtextfile.txt", mode="r", newline="")
file.read()
file=open("mynewtextfile.txt", mode="r", newline=None)
file.read()
file.close()
编码方式
encoding表示字符编码, 这是一种使用位和字节表示字符的编码系统。在谈论数据存储, 数据传输和计算时, 经常会出现这个概念。
由于默认编码取决于Microsoft Windows的操作系统, 因此默认编码为cp1252, 但在Linux中为UTF-8。因此, 在处理文本文件时, 最好指定字符编码。请注意, 二进制模式不使用编码参数。
之前, 你读到可以使用errors参数处理编码和解码错误, 并且可以使用换行符处理行尾。现在, 尝试以下代码:
with open("mynewtextfile.txt", mode="r") as file:
print("Default encoding:", file.encoding)
file.close()
##change encoding to utf-8
with open("mynewtextfile.txt", mode="r", encoding="utf-8") as file:
print("New encoding:", file.encoding)
file.close()
关闭
如果closefd为False且给出了文件描述符而不是文件名, 则在关闭文件时, 底层文件描述符将保持打开状态。如果提供了文件名, 则必须将closefd设置为True, 这是默认设置。否则, 你可能会得到一个错误。你可以使用此参数将现有文件描述符包装到实际文件对象中。
请注意, 文件描述符只是操作系统分配给文件对象的整数, 因此Python可以请求I / O操作。方法.fileno()返回此整数。
如果你已经为I / O通道打开了一个整数文件描述符, 则可以围绕它包装一个文件对象, 如下所示:
file=open("mynewtextfile.txt", "r+")
fd=file.fileno()
print("File descriptor assigned:", fd)
# Turn the file descriptor into a file object
filedes_object=open(fd, "w")
filedes_object.write("Data sciences\r\nPython")
filedes_object.close()
在这种情况下, filedes_object将关闭基础文件对象文件。关闭文件将提供OSError错误的文件描述符:
file.close()
为了防止关闭基础文件对象, 可以使用closefd = False:
file=open("mynewtextfile.txt", "r+")
fd=file.fileno()
print("File descriptor assigned:", fd)
# Turn the file descriptor into a file object
filedes_object=open(fd, "w", closefd=False)
filedes_object.write("Hello")
filedes_object.close()
file.close()
到目前为止, 你已经学到了很多有关使用Python读取文本文件的知识, 但是, 由于你在本教程中已经阅读了很多次, 所以这些并不是你可以导入的唯一文件:还有二进制文件。
但是这些二进制文件到底是什么?
二进制文件以机器可读的方式将数据存储在0和1中。一个字节是8位的集合。一个字符将一个字节存储在8位内存中。例如, 字符” H”的二进制表示形式是01001000, 然后将此8位二进制字符串转换为十进制, 则得出72。
binary_file=open("D:\\new_dir\\binary_file.bin", mode="wb+")
text="Hello 123"
encoded=text.encode("utf-8")
binary_file.write(encoded)
binary_file.seek(0)
binary_data=binary_file.read()
print("binary:", binary_data)
text=binary_data.decode("utf-8")
print("Decoded data:", text)
当你打开文件以二进制模式b进行读取时, 它将返回数据字节。
如果你需要从二进制文件中读取或写入文本, 请确保记得像上面那样对它进行解码或编码。你可以像下面这样通过迭代访问每个字节, 它将返回整数字节值(每个字符的8位二进制表示形式的十进制), 而不是字节字符串:
for byte in binary_data:
print(byte)
Python文件对象属性
文件属性提供有关文件和文件状态的信息。
属性 | 函数 |
---|---|
名称 | 返回文件名 |
关闭 | 如果文件已关闭, 则返回true。否则为假。 |
模式 | 文件打开的模式。 |
软空间 | 返回一个布尔值, 该布尔值指示在使用print语句时是否需要在另一个值之前打印空格字符。 |
编码方式 | 文件的编码 |
# This is just another way you can open a file
with open("D:\\new_dir\\anotherfile.txt") as file:
print("Name of the file:", file.name)
print("Mode of the file:", file.mode)
print("Mode of the file:", file.encoding)
file.close()
print("Closed?", file.closed)
文件对象的其他方法
方法 | 函数 |
---|---|
readable() | 返回文件是否可读的True / False |
writable() | 文件是否可写返回True / False |
fileno() | 返回Python用来从操作系统请求I / O操作的Integer描述符 |
flush() | 清除文件的内部缓冲区。 |
isatty() | 如果文件连接到Teletytywriter(TTY)设备或类似设备, 则返回True。 |
truncate([size) | 截断文件, 最多指定字节。 |
next(iterator, [default]) | 当文件用作迭代器时, 对文件进行迭代;当到达文件末尾(EOF)进行读取时, 停止迭代。 |
让我们尝试所有这些方法:
with open("mynewtextfile.txt", "w+") as f:
f.write("We are learning python\nWe are learning python\nWe are learning python")
f.seek(0)
print(f.read())
print("Is readable:", f.readable())
print("Is writeable:", f.writable())
print("File no:", f.fileno())
print("Is connected to tty-like device:", f.isatty())
f.truncate(5)
f.flush()
f.seek(0)
print(f.read())
f.close()
通过os模块处理文件
Python的os模块允许你执行与操作系统有关的操作, 例如制作文件夹, 列出文件夹的内容, 了解进程, 结束进程等。它具有查看Python所在操作系统的环境变量的方法。工作等等。这是os模块的Python文档。
让我们看一些有用的os模块方法, 这些方法可以帮助你处理程序中的文件和文件夹。
方法 | 函数 |
---|---|
os.makedirs() | 新建一个文件夹 |
os.listdir() | 列出文件夹的内容 |
os.getcwd() | 显示当前工作目录 |
os.path.getsize() | 显示参数中传递的文件大小(以字节为单位) |
os.path.isfile() | 传递参数文件 |
os.path.isdir() | 传递参数一个文件夹 |
os.chdir | 更改目录/文件夹 |
os.rename(当前, 新) | 重命名文件 |
os.remove(文件名) | 删除档案 |
让我们看一下这些方法的一些例子:
import os
os.getcwd()
'C:\\Users\\HAFSA-J'
os.makedirs("D:\\my_folder")
---------------------------------------------------------------------------
FileExistsError Traceback (most recent call last)
<ipython-input-6-346b12771465> in <module>()
----> 1 os.makedirs("D:\\my_folder")
C:\Users\HAFSA-J\Anaconda3\lib\os.py in makedirs(name, mode, exist_ok)
218 return
219 try:
--> 220 mkdir(name, mode)
221 except OSError:
222 # Cannot rely on checking for EEXIST, since the operating system
FileExistsError: [WinError 183] Cannot create a file when that file already exists: 'D:\\my_folder'
下一个代码块将在D驱动器中创建一个名为My_folder的文件夹:
open("D:\\my_folder\\newfile.txt", "w")
print("Contents of folder D:\\my_folder\n", os.listdir("D:\\my_folder"))
print("---------------------------------")
print("Size of folder D:\my_folder (in bytes)", os.path.getsize("D:\\my_folder"))
print("Is file?", os.path.isfile("D:\\new_dir"))
print("Is folder?", os.path.isdir("D:\\new_dir\\anotherfile.txt"))
os.chdir("D:\\my_folder")
os.rename("newfile.txt", "hello.txt")
print("New Contents of folder D:\\my_folder\n", os.listdir("D:\\my_folder"))
Contents of folder D:\my_folder
['hello.txt', 'newfile.txt']
---------------------------------
Size of folder D:\my_folder (in bytes) 0
Is file? False
Is folder? False
---------------------------------------------------------------------------
FileExistsError Traceback (most recent call last)
<ipython-input-9-4884bcddc38c> in <module>()
6 print("Is folder?", os.path.isdir("D:\\new_dir\\anotherfile.txt"))
7 os.chdir("D:\\my_folder")
----> 8 os.rename("newfile.txt", "hello.txt")
9 print("New Contents of folder D:\\my_folder\n", os.listdir("D:\\my_folder"))
FileExistsError: [WinError 183] Cannot create a file when that file already exists: 'newfile.txt' -> 'hello.txt'
如果你创建的文件名已经存在, Python将给出FileExistsError错误。要删除使用的文件, 可以使用os.remove(filename):
os.getcwd()
os.remove("hello.txt")
print("New Contents of folder D:\\my_folder\n", os.listdir("D:\\my_folder"))
os.chdir("C:\\Users\\Hafsa-J")
这全都与平面文件有关!如果你想学习如何从Excel工作表中导入数据, 请查看本教程。
哇!
在开始之前, 你绝对应该检查Python的出色数据处理库熊猫:请参阅本教程, 以获取处理数据的更多好方法。
教程到此结束!现在你知道了如何在Python中处理文件以及从创建到操作系统级处理的操作。
评论前必须登录!
注册