Pythonファイル処理方法サンプルコード解析

WBOY
リリース: 2023-05-12 20:16:04
転載
1087 人が閲覧しました

ファイルを開く

最も基本的なファイル読み取りの例から始めましょう。コード ファイルと同じディレクトリに journal1.txt.

というファイルがあるとします。ファイルを開く標準的な方法は、組み込みの open( )関数。デフォルトでは io モジュールからインポートされます。

file = open("journal1.txt", 'r')
for line in file:
    print(line)
file.close()
ログイン後にコピー

open()この関数は、高度な方法でファイルを操作するために多くのパラメーターを受け入れますが、ほとんどの場合、最初の 2 つのパラメーターのみが必要です

1 つの引数 file は、開いているファイルへの絶対パスまたは相対パスを含む文字列を受け入れます。これは厳密に必要な唯一のパラメータです。

2 番目のパラメータ mode は、 ファイル モード を示す文字列を受け入れます。指定しない場合は、'rt' が使用されます。これは、ファイルをテキストとして読み取ることを意味します。テキスト モード (t) はデフォルトの動作の一部であるため、モード 'r' は実際には同じです。

代わりにこの行を使用すると、同じ動作が得られます。 。 。

file = open("journal1.txt")
ログイン後にコピー

しかし、個人的には、自分が読んでいるのか (r)、書いているのか (w)、あるいは何をしているのかを明確に述べたいと思っています。

open()<strong> から返されるすべての「ファイル」オブジェクトは反復可能です。 </strong>テキスト ファイルの場合は、TextIOWrapper オブジェクトを返します。上の例では、TextIOWrapper オブジェクト ファイル内の行をループし、各行を出力します。 ファイルを処理した後、file.close()

を使用してファイルを閉じる必要があります。

ガベージ コレクターによるファイルのクローズに依存しないことが重要です。この動作は保証されておらず、実装が便利でもありません。さらに、Python は、.close() を呼び出す前にファイルへの書き込みが完了することを保証しません。 このコードを実行しても、少なくとも私の場合は、journal1.txt 内容:

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 は出力されません。実際には、常に

close()

の呼び出しは、特にファイルを開くときに発生する可能性のあるエラーを考慮すると、非常に面倒な作業になる可能性があることに注意してください。ありがたいことに、もっと簡単な方法があります:

コンテキスト マネージャー

! コンテキスト マネージャーは、Python の

with

ステートメントによって定義されます。次の構文を使用して、以前のコードを書き直すことができます。

with open("journal1.txt", 'r') as file:
    for line in file:
        print(line)
ログイン後にコピー
open() 関数を呼び出し、成功すると、結果の

TextIOWrapper

オブジェクトが ## に保存されます。 #file であり、with ステートメントの本文で使用できます。 file.close() は、コントロールが with ステートメントを離れると暗黙的に呼び出されるため、呼び出すことを覚えておく必要はありません。 これについては、次の章でさらに詳しく説明します。 ファイル モード

ドキュメントには、

open()

で使用できるいくつかのモードが記載されています:

r

読み取り用にファイルを開きます (デフォルト)。
  • #w

    ファイルを開くか作成して最初に書き込み、その内容を削除 (切り詰め) します。
  • #a

    書き込み用にファイルを開くか作成しますが、切り詰めるのではなく末尾に追加します。
  • #xxx

    書き込み用に新しいファイルを作成して開きます。既存のファイルを開くことはできません。
  • 読み取りおよび書き込みのためにファイルを開きます (以下の表を参照)。
  • #t

    ファイルをテキスト モードで処理します (デフォルト)。
  • #b

    ファイルをバイナリ モードで処理します。
  • これらのモード フラグは組み合わせて使用​​できます。たとえば、バイナリ モードでは、 a b により書き込みと読み取りが可能になり、ファイルの最後に書き込みが追加されます。

    フラグは常に別のフラグと組み合わされます。
  • r
と組み合わせると、

a

の機能が追加されますが、ファイルの先頭から開始されます (切り詰められません)。

wa、または x と組み合わせて読み取ることもできます。 さまざまなフラグの動作は、次の表を使用すると最もよく理解できます:

| 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

read()

,

を使用できます。 readline ()

または

readlines() 関数は、テキスト モードでファイルを読み取るか、直接反復処理します。 もちろん、これには、適切なファイル モード フラグ ( 「ファイルモード」セクションを参照してください)。オブジェクト ファイルが読み取れるかどうかを確認する必要がある場合は、file.readable() 関数を使用します。

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

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())
ログイン後にコピー

以上がPythonファイル処理方法サンプルコード解析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:yisu.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート