Home  >  Article  >  Backend Development  >  Python file processing method example code analysis

Python file processing method example code analysis

WBOY
WBOYforward
2023-05-12 20:16:041084browse

Open File

Let’s start with the most basic file reading example. Let's say I have a file in the same directory as my code file called journal1.txt.

The standard way to open a file is to use the built-in open()Function, imported from io module by default.

file = open("journal1.txt", 'r')
for line in file:
    print(line)
file.close()

open()The function accepts many parameters for interacting with files in advanced ways, but in most cases you only need the first two parameters

One argument file accepts a string containing the absolute or relative path to the open file. This is the only strictly required parameter.

The second parameter mode accepts a string indicating the file mode. If not specified, 'rt' will be used, which means it reads the file as text. Mode 'r' is actually the same since text mode ( t) is part of the default behavior.

I can use this line instead and get the same behavior. . .

file = open("journal1.txt")

But I personally prefer to explicitly state whether I'm reading (r), writing (w), or what have you.

All "file" objects returned from <strong>open()</strong> are iterable. For text files, returns a TextIOWrapper object. In the example above, I loop through the lines in the TextIOWrapper object file and print out each line.

After processing the file, I need to close it using file.close(). It is important not to rely on the garbage collector to close files for you, as this behavior is neither guaranteed nor convenient to implement. Additionally, Python does not guarantee that writing to the file will complete before calling .close().

Running this code, at least in my case, does not print out journal1.txt Contents:

Could this be where all missing things are found?

Magic Hair Only for the Pure of Heart

Not naturally occurring?

Could result in minor gravity anomalies!

Context Manager

In practice , always remember that calling close() can be a real pain, especially when you consider the errors that can occur when opening a file. Thankfully, there's a simpler way: Context Manager!

Context managers are defined by the with statement in Python. I can rewrite my previous code using the following syntax:

with open("journal1.txt", 'r') as file:
    for line in file:
        print(line)

Calls the open() function, and if successful, the resulting TextIOWrapper object is stored in file, and can be used in the body of a with statement. file.close() is called implicitly once control leaves the with statement; you never have to remember to call it!

We'll cover this in more depth in the next chapter.

File Modes

The documentation mentions several modes available for open():

  • r Open the file for reading (default).

  • #wOpen or create a file to first write, delete (truncate) its contents.

  • #aOpen or create a file for writing, but append to the end rather than truncate.

  • #xCreates and opens a new file for writing; it cannot open an existing file.

  • Open the file for reading and writing (see table below).

  • #t Process files in text mode (default).

  • #b Process files in binary mode.

These mode flags can be combined together. For example, in binary mode, a b allows writing and reading, with writes appended to the end of the file. The

flag is always combined with another flag. When combined with r, it adds the functionality of a, but it starts at the beginning of the file (without truncation). It also allows reading when combined with w, a, or x.

The behavior of the different flags can best be understood using this table:

| r   r+   w   w+   a   a+   x   x+
---------------------|----------------------------------
allow read           | ✓   ✓        ✓        ✓        ✓
allow write          |     ✓    ✓   ✓    ✓   ✓    ✓   ✓
create new file      |          ✓   ✓    ✓   ✓    ✓   ✓
open existing file   | ✓   ✓    ✓   ✓    ✓   ✓
erase file contents  |          ✓   ✓
allow seek           |     ✓    ✓   ✓             ✓   ✓
position at start    | ✓   ✓    ✓   ✓             ✓   ✓
position at end      |                   ✓   ✓

read

We can use read(), readline () or readlines() function reads the file in text mode, or iterates directly

Of course, this requires opening the file for reading with the appropriate file mode flag (please See the "File Mode" section). If you need to check whether the object file can be read, use the file.readable() function.

让我们对比一下读取文件的三种方式:

read()

read()函数将文件的全部内容作为一个长字符串读取。

with open("journal1.txt", 'r') as file:
    contents = file.read()
    print(contents)

# Could this be where all missing things are found?
# Magic Hair Only for the Pure of Heart
# Not naturally occurring?
# Could result in minor gravity anomalies!

或者,你可以告诉read()从文件流中读取的最大字符数:

with open("journal1.txt", 'r') as file:
    contents = file.read(20)
    print(contents)

# Could this be where

readline()

readline()函数的行为与read()完全相同,只是它在遇到换行符时停止读取。换行符包含在返回的字符串中。

with open("journal1.txt", 'r') as file:
    contents = file.readline()
    print(contents)

# Could this be where all missing things are found?

read()一样,你可以指定要读取的最大字符数:

with open("journal1.txt", 'r') as file:
    contents = file.readline(20)
    print(contents)

# Could this be where

readlines()

readlines()函数以字符串列表的形式返回整个文件,每个字符串为一行。

with open("journal1.txt", 'r') as file:
    contents = file.readlines()
    for c in contents:
        print(c)

# Could this be where all missing things are found?
#
# Magic Hair Only for the Pure of Heart
#
# Not naturally occurring?
#
# Could result in minor gravity anomalies!
#

你会注意到每一行都包含换行符。我们可以通过在每个字符串上调用.strip()函数来删除它。

with open("journal1.txt", 'r') as file:
    contents = file.readlines()
    for c in contents:
        print(c.strip())

# Could this be where all missing things are found?
# Magic Hair Only for the Pure of Heart
# Not naturally occurring?
# Could result in minor gravity anomalies!

你还可以通过指定最大字符数来限制从文件中读取的内容。然而,与以前不同的是,这不是硬性限制。相反,一旦到目前为止从所有行读取的字符总数超过了指定的限制,则只会读取当前行的其余部分。

通过比较read()readlines()可以最好地理解这一点。首先,我将阅读限制为60个字符:

with open("journal1.txt", 'r') as file:
    contents = file.read(60)
    print(contents)

# Could this be where all missing things are found?
# Magic Hair

readlines()与使用 60 个字符的“提示”进行比较:

with open("journal1.txt", 'r') as file:
    contents = file.readlines(60)
    for c in contents:
        print(c.strip())

# Could this be where all missing things are found?
# Magic Hair Only for the Pure of Heart

在第二个示例中,读取前两行的全部内容,但不再读取。

与其他两个函数不同,readlines()总是读取整行。

迭代

如你之前所见,我们可以直接迭代文件:

with open("journal1.txt", 'r') as file:
    for line in file:
        print(line)

# Could this be where all missing things are found?
# Magic Hair Only for the Pure of Heart
# Not naturally occurring?
# Could result in minor gravity anomalies!

这在功能上与以下内容相同:

with open("journal1.txt", 'r') as file:
    for line in file.readlines():
        print(line)

两者的区别在于第一种方法,直接迭代,是惰性的,而第二种方法在迭代内容之前首先读取整个文件。

使用write()orwritelines()函数,我们可以以几乎相同的方式写入文件。

这需要打开文件进行写入(参见“文件模式”部分)。file.writable()函数可用于检查file对象是否可写。

在本节的示例中,我将在底部的注释中显示文件内容。

write()

write()函数将给定的行写入文件。

我可以使用write()将整个多行字符串写入一个名为journal3.txt的新文件,如下所示:

entry = """If you go on enough road trips
chances are, you've seen a
certain bumper sticker:
WHAT IS THE MYSTERY SHACK?
"""

with open("journal3.txt", 'x') as file:
    file.write(entry)

# If you go on enough road trips
# chances are, you've seen a
# certain bumper sticker:
# WHAT IS THE MYSTERY SHACK?
#

只要journal3.txt存在,它将使用给定的内容创建。

我可以使用w文件模式覆盖journal3.txt的全部内容:

with open("journal3.txt", 'w') as file:
    file.write("GNOMES\nWEAKNESS?\n")

# GNOMES
# WEAKNESS?
#

注意:注意你的文件模式!w并将w+删除文件的全部内容。使用aa+写入文件末尾。

我可以使用a文件模式附加到文件中:

with open("journal3.txt", 'a') as file:
    file.write("leaf blowers\n")

# GNOMES
# WEAKNESS?
# leaf blowers
#

write()函数返回一个整数,表示写入的字符数。

writelines()

writelines()函数将字符串列表写入文件。

lines = [
    "Finally back safe and sound\n",
    "from one of the weirdest days\n",
    "at Gravity Falls.\n"
]

with open("journal3.txt", 'w') as file:
    file.writelines(lines)

# Finally back safe and sound
# from one of the weirdest days
# at Gravity Falls.
#

与 withwrite() 不同,writelines()函数只返回None

搜索

file.seek()函数允许你在文件对象file中逐个字符地来回移动。处理文本流时,它接受一个参数:一个正整数,表示要移动到的新位置,表示为从开头开始的字符数。

除了改变位置之外,该file.seek()函数还将返回一个表示文件中新绝对位置的整数。你可用file.tell()来获取该文件的当前位置。

r+文件模式最好与函数seek()一起使用,尽管它可以与 aa+之外的任何其他文件模式一起使用。

我将首先使用seek()函数来读取journal1.txt文件的一部分:

with open("journal1.txt", 'r') as file:
    file.seek(50)
    contents = file.read(5)
    print(contents)

# MAGIC

我将编写journal3.txt文件的新初始版本:

with open("journal3.txt", 'w') as file:
    file.write("FLOATING EYEBALLS")

# FLOATING EYEBALLS

我可以使用该r+模式更改此文件的一部分。

注意:write()命令将始终覆盖文件的现有内容,除非你追加到末尾。要将文本非破坏性地插入文件,通常最好将整个内容作为字符串(或列表)读取,编辑字符串,然后将其写回。

在这里,我将用“NONSENSE!”替换“EYEBALLS”这个词:

with open("journal3.txt", 'r+') as file:
    file.seek(9)
    file.write("NONSENSE!")

# FLOATING NONSENSE!

打开文件后,我从头移动到第 9 个字符,然后write()是新数据。

用二进制搜索

当你以二进制模式 ( b) 打开文件时,你可以以更动态的方式在文件中移动,使用两个参数而不是一个参数:

  • offset:字符移动的距离(可以是负数)

  • whence: 计算偏移量的位置:0表示文件的开始位置(默认),1表示当前位置,2表示文件的结束位置。

不幸的是,使用whence参数不适用于以文本模式打开的文件。

文件错误

与处理文件相关的四个最常见错误如下:

FileNotFoundError

rr+模式要求文件在打开之前存在。否则,将引发FileNotFoundError错误:

try:
    with open("notreal.txt", 'r') as file:
        print(file.read())
except FileNotFoundError as e:
    print(e)

FileExistsError

xx+文件模式专门用于创建新文件。如果文件已存在,将引发FileExistsError错误:

try:
    with open("journal3.txt", 'x+') as file:
        print(file.read())
except FileExistsError as e:
    print(e)

UnsupportedOperation

每当你尝试读取仅打开用于写入的文件或写入仅打开用于读取的文件时都会引发错误io.UnsupportedOperation

import io

try:
    with open("journal3.txt", 'w') as file:
        print(file.read())
except io.UnsupportedOperation as e:
    print(e)


try:
    with open("journal3.txt", 'r') as file:
        file.write('')
except io.UnsupportedOperation as e:
    print(e)

换行符的问题

一些聪明的读者会记得,虽然UNIX使用\n作为行分隔符,但Windows使用\r\n。当我们读写文件时,这肯定很重要,对吧?

事实上,Python 在幕后为我们抽象了这一点。无论操作系统如何,在以文本模式写入文件时始终用作行分隔符!<strong>\n</strong>

文件路径

到目前为止,我只使用了与代码相同文件夹中的文件,但这很少是我们想要的!我们需要能够构建文件路径。

问题是,所有系统上的文件路径都不相同。UNIX风格的系统,如macOS和Linux,使用UNIX文件路径约定,而Windows使用完全不同的方案。我们的解决方案必须对两者都有效,这意味着硬路径不是一个选项。

为了解决这个问题,Python 提供了两个模块:ospathlib

创建路径

Python实际上提供了多个用于构建路径的类,这取决于你的特定需求。但是,在大多数情况下,你应该只使用pathlib.Path

假设我想在当前用户的主文件夹中创建一个名为.dead_simple_python的特殊目录,然后将文件写入该位置。我会这样做:

首先,我创建一个Path()对象,指向最终所需的目录(而不是文件)。

Path()构造函数中,我将路径的每个部分作为单独的字符串传递。我可以使用类方法Path.home()来获取用户目录的路径。

from pathlib import Path
import os

file_path = Path(Path.home(), ".dead_simple_python")

接下来,我将使用file_path.exists()检查路径是否已经存在。如果它不存在,我将使用os.makedirs函数用于创建路径中缺少的任何目录:

if not file_path.exists():
    os.makedirs(file_path)

最后,我可以将文件名添加到已经拥有的路径对象中,然后打开该文件进行写入:

file_path = file_path.joinpath("journal4.txt")

with file_path.open('w') as file:
    lines = [
        "If you've ever taken a road trip \n",
        "through the Pacific Northwest, you've \n",
        "probably seen a bumper sticker for a \n",
        "place called Gravity Falls.\n"
    ]
    file.writelines(lines)

你会注意到我使用了file_path.open('w'),而不是open(file_path, 'w')。从技术上讲,两者的作用完全相同,尽管成员函数是首选。

相对路径

open("journal1.txt")之所以有效,是因为它是一个相对路径,从执行代码的目录开始。

如果我的代码所在的目录中有一个journals/目录,我可以使用它:

from pathlib import Path

file_path = Path("journals", "journal1.txt")

with file_path.open('r') as file:
    print(file.read())

只要我不是从绝对路径开始,比如由Path.home()生成的路径,路径都是相对的。

但是如果我想向上移动一个目录而不是向下移动呢?你可能会尝试使用..,但正如你可能猜到的,这并不能保证在所有操作系统上都是可移动的。相反,我可以使用os.pardir移动到上一个目录。

想象一下,我们有一个如下所示的目录结构:

example
├── code
│   └── read_file.py
└── journals
    └── journal1.txt

如果在path_relative2/code运行python read_file.py,我可以通过以下方式访问journal1.txt

from pathlib import Path
import os

file_path = Path(os.pardir, "journals", "journal1.txt")

with file_path.open('r') as file:
    print(file.read())

The above is the detailed content of Python file processing method example code analysis. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete