Pythonでビッグデータファイルを読み取る

Pythonでビッグデータファイルを読み取る

Python では、大きなファイルを読み取るシナリオがよく発生します。ファイルが小さい場合は、通常、次のメソッド readlines() を使用します。このメソッドは、ファイルのすべての行を一度に読み取り、リストに入れ、最後にメモリに保存しますファイルが大きい場合、メモリ使用量が非常に多くなり、メモリ オーバーフローが発生し、プロセスがシステムによって強制終了される可能性もあります。

# 读取方式一
with open(file_path, 'r+', encoding='utf-8') as f:
    count = 0
    for line in f.readlines():
        count += 1
    print(count)

実行前:
総システム メモリ: 8056.3M
システム使用メモリ: 6264.3M
システム空きメモリ: 1791.3M
20465実行
後:
総システム メモリ: 8056.3M
システム使用メモリ: 6266.3M
システム空きメモリ: 1789.3M

実験で使用したファイルサイズは800kとそれほど大きくはありませんが、 2Mのメモリを占有していることがわかります

推奨される方法: イテレータ反復走査

Pythonにはイテレータという概念があります。反復は、実際にはシーケンス内の要素を処理する方法です

次に、反復可能オブジェクトを使用して反復処理を行い、そのメモリ使用量をテストします。f の行では、キャッシュ IO とメモリ管理が自動的に使用されます

# 读取方式二
with open(file_path, 'r+', encoding='utf-8') as f:
    count = 0
    for line in f:
        count += 1
    print(count)

実行前:
総システム メモリ: 8056.3M
システム使用メモリ: 5883.3M
システム空きメモリ: 2172.3M
20465
実行後:
総システム メモリ: 8056.3M
システム使用メモリ: 5884.3M
システム空きメモリ: 2171.3M

実験で使用したファイルのサイズは 800k とそれほど大きくはありませんが、使用するメモリは 1M であり、最初の方法に比べてメモリが節約されていることがわかります。

推奨される方法: ジェネレーター

ジェネレーターは、イテレーターを作成するためのシンプルかつ強力なツールです。これは、データを返すときに yield ステートメントを使用する必要があることを除いて、通常の関数のように記述されます。

# 读取方式三
# 生成器函数,用于自定义创建迭代器read_fileline_generator
def read_fileline_generator(file, size=4096):
    while 1:
        data = file.read(size)
        if not data:
            break
        yield data


with open(file_path, 'r+', encoding='utf-8') as f:
    count = 0
    for line in read_fileline_generator(f):
        count += 1

実行前:
総システム メモリ: 8056.3M
システム使用メモリ: 5719.3M
システム空きメモリ: 2336.3M
実行後:
総システム メモリ: 8056.3M
システム使用メモリ: 5720.3M
システム空きメモリ: 2335.3M

実験で使用したファイルのサイズは 800k とそれほど大きくはありませんが、使用するメモリは 1M であり、最初の方法に比べてメモリが節約されていることがわかります。

ビルダー

上記では、ジェネレーターを使用してファイルを反復処理するイテレーターを作成しました。では、発電機とは何でしょうか?配列を返す関数のようなジェネレーターを詳しく見てみましょう。

反復プロトコルをサポートするために、yield ステートメントを含む関数はジェネレーターにコンパイルされます。このタイプの関数が呼び出されると、ジェネレーター オブジェクトが返されます。返されたオブジェクトは反復インターフェイス、つまりメンバー メソッド __next( )__ は中断された時点から実行を継続します。

ただし、通常の関数とは異なります。

一般関数は一度にすべての値の配列を返しますが、ジェネレーター関数は一度に配列内の値を 1 つだけ生成するため、消費されるメモリは大幅に削減されます。

一般的な関数は実行後、値を返して終了しますが、ジェネレーター関数は、yield キーワードを使用して呼び出し元に値を返し、現在の実行状態を保持し、自動的に一時停止するため、次の実行時に実行を継続できます。後で呼ばれました。

ジェネレーターに next() 関数を使用するのは面倒ですが、for ループによってジェネレーターの next 関数が自動的にトリガーされます。

Python には 2 種類のジェネレーターがあります。

  • **ジェネレーター関数:** も def によって定義されており、キーワード yield を使用して一度に 1 つの結果を返し、ブロックして再開します。
  • **ジェネレータ式:** 必要な場合にのみ結果を生成するオブジェクトを返します

上ではジェネレーター関数を適用しましたが、ジェネレーター式とは何でしょうか?

ジェネレータ式はリスト内包表記に似ていますが、リスト内包表記では角括弧の代わりに括弧を使用します。

# 列表解析式
list = [ x**2 for x in range(5)]
print(list)
[0, 1, 4, 9, 16]

# 生成器表达式
generator_list = (x**2 for x in range(5))
print(generator_list)
<generator object <genexpr> at 0x0EE83840>
print(next(generator_list))
0
print(next(generator_list))
1
print(next(generator_list))
4
print(next(generator_list))
9
print(next(generator_list))
16
print(next(generator_list))
Traceback (most recent call last):
  File "<input>", line 1, in <module>
StopIteration

テストコード

# python 读取较大数据文件

import psutil

mem = psutil.virtual_memory()
print('运行前:')
print('系统总计内存:%d.3M' % (float(mem.total)/1024/1024))
print('系统已经使用内存:%d.3M' % (float(mem.used)/1024/1024))
print('系统空闲内存:%d.3M' % (float(mem.free)/1024/1024))


file_path = 'H:\\study\\python\\long.txt'

# 读取方式一
# with open(file_path, 'r+', encoding='utf-8') as f:
#     count = 0
#     for line in f.readlines():
#         count += 1
#     print(count)

# 读取方式二
# with open(file_path, 'r+', encoding='utf-8') as f:
#     count = 0
#     for line in f:
#         count += 1
#     print(count)


# 读取方式三
def read_fileline_generator(file, size=4096):
    while 1:
        data = file.read(size)
        if not data:
            break
        yield data


with open(file_path, 'r+', encoding='utf-8') as f:
    count = 0
    for line in read_fileline_generator(f):
        count += 1

mem2 = psutil.virtual_memory()
print('运行后:')
print('系统总计内存:%d.3M' % (float(mem2.total) / 1024 / 1024))
print('系统已经使用内存:%d.3M' % (float(mem2.used) / 1024 / 1024))
print('系统空闲内存:%d.3M' % (float(mem2.free) / 1024 / 1024))

おすすめ

転載: blog.csdn.net/jane_xing/article/details/120332665