ホームページ  >  記事  >  バックエンド開発  >  Python オブジェクトのシリアル化と逆シリアル化: パート 2

Python オブジェクトのシリアル化と逆シリアル化: パート 2

PHPz
PHPzオリジナル
2023-09-03 20:33:051437ブラウズ

Python 对象序列化和反序列化:第 2 部分

これは、Python オブジェクトのシリアル化と逆シリアル化に関するチュートリアルの 2 番目の部分です。最初のパートでは、基本を学び、次に Pickle と JSON の詳細を掘り下げました。

このパートでは、YAML について学び (パート 1 の実行例を必ず入手してください)、パフォーマンスとセキュリティに関する考慮事項について説明し、他のシリアル化形式について学び、最後に適切なシリアル化形式を選択する方法を学びます。 p>

YAML

YAML は私のお気に入りの形式です。これは人間にとって使いやすいデータシリアル化形式です。 Pickle や JSON とは異なり、Python 標準ライブラリの一部ではないため、インストールする必要があります:

pip インストール yaml

yaml モジュールには、load() 関数と dump() 関数のみがあります。デフォルトでは、loads()dumps() のような文字列を受け取りますが、オープン ストリームである 2 番目の引数を受け取り、ファイルにダンプ/ロードしたり、ファイルからロードしたりすることもできます。

リーリー

Pickle や JSON と比較して、YAML がどれほど読みやすいかに注目してください。ここからが YAML のすごいところです。YAML は Python オブジェクトを理解します。カスタムのエンコーダやデコーダは必要ありません。 YAML を使用した複雑なシリアル化/逆シリアル化は次のとおりです:

リーリー

ご覧のとおり、YAML には Python オブジェクトをマークするための独自の表記法があります。出力は依然として非常に読みやすいです。 YAML は本質的に日時オブジェクトをサポートしているため、日時オブジェクトには特別なマークアップは必要ありません。

###パフォーマンス###

パフォーマンスについて考え始める前に、パフォーマンスが問題かどうかを検討する必要があります。少量のデータを比較的頻繁にシリアル化/逆シリアル化する場合 (プログラムの先頭で構成ファイルを読み取る場合など)、パフォーマンスは実際には問題ではないため、そのまま続行できます。

ただし、システムのプロファイリングを行って、シリアル化および/または逆シリアル化がパフォーマンスの問題を引き起こしていることが判明した場合は、次の問題に対処する必要があります。

パフォーマンスには 2 つの側面があります。シリアル化/逆シリアル化の速度と、シリアル化された表現の大きさです。

さまざまなシリアル化形式のパフォーマンスをテストするために、より大きなデータ構造を作成し、Pickle、YAML、および JSON を使用してシリアル化/逆シリアル化します。

big_data

リストには 5,000 個の複雑なオブジェクトが含まれています。 リーリー ピクルス

IPython には実行時間を測定する便利な

%timeit

マジック関数があるため、ここでは IPython を使用します。 リーリー デフォルトの pickle は、シリアル化に 83.1 ミリ秒、逆シリアル化に 29.2 ミリ秒かかり、シリアル化のサイズは 747,328 バイトです。

最上位のプロトコルを使用してみましょう。

リーリー

興味深い結果です。シリアル化時間はわずか 21.2 ミリ秒に減少しましたが、逆シリアル化時間は 25.2 ミリ秒にわずかに増加しました。シリアル化されたサイズは 394,350 バイト (52%) に大幅に減少します。

JSON

リーリー ###わかりました。エンコードのパフォーマンスは Pickle よりも少し悪いように見えますが、デコードのパフォーマンスははるかに悪く、6 倍も遅くなります。これはどうなっているでしょうか?これは

object_hook

関数のアーティファクトであり、辞書をオブジェクトに変換する必要があるかどうかをチェックするために辞書ごとに実行する必要があります。オブジェクトフックを使用しないと、はるかに高速に実行されます。

リーリー ここでの教訓は、JSON へのシリアル化および逆シリアル化の際にカスタム エンコーディングを慎重に検討することです。カスタム エンコーディングは全体的なパフォーマンスに大きな影響を与える可能性があります。

YAML

リーリー ###わかりました。 YAML は本当に遅いです。ただし、興味深いことに注意してください。シリアル化されたサイズはわずか 200,091 バイトです。 Pickle と JSON の両方よりもはるかに優れています。内部を簡単に見てみましょう:

リーリー

YAML はここで非常に賢いです。 5,000 個の辞書すべてが同じ「a」キー値を共有していると判断するため、それを 1 回だけ保存し、すべてのオブジェクトに対して

*id001

を使用して参照します。

###安全性###

セキュリティは多くの場合重要な問題です。 Pickle と YAML は、Python オブジェクトの構築によりコード実行攻撃に対して脆弱です。適切にフォーマットされたファイルには、Pickle または YAML によって実行される任意のコードが含まれる可能性があります。パニックになる必要はありません。これは仕様であり、Pickle のドキュメントに記載されています: 警告: pickle モジュールは、誤ったデータや悪意を持って構築されたデータから保護するように設計されていません。信頼できないソースまたは認証されていないソースから受信したデータは決してキャンセルしないでください。

そして YAML ドキュメントの内容:

警告: 信頼できないソースから受信したデータを使用して yaml.load を呼び出すのは安全ではありません。 yaml.load は pickle.load と同じくらい強力なので、任意の Python 関数を呼び出すことができます。

信頼できないソースから受信したシリアル化されたデータを読み込むために、Pickle または YAML を使用しないでください。 JSON は問題ありませんが、カスタム エンコーダ/デコーダを使用している場合も同様に危険にさらされる可能性があります。

yaml モジュールは、単純なオブジェクトのみをロードする

yaml.safe_load()
関数を提供しますが、そうすると YAML の機能の多くが失われ、JSON のみを使用することを選択する可能性があります。

その他の形式

他にも利用可能なシリアル化形式が多数あります。ここではその一部を紹介します。

プロトコルバッファ

Protobuf (つまり、プロトコル バッファ) は、Google のデータ交換形式です。 C で実装されていますが、Python バインディングがあります。洗練されたアーキテクチャを備えており、データを効率的にパッケージ化します。非常に強力ですが、あまり使いやすいものではありません。

メッセージパッケージ

MessagePack も人気のあるシリアル化形式です。これもバイナリで効率的ですが、Protobuf とは異なり、スキーマを必要としません。 JSON に似た型システムを持っていますが、より豊富です。キーは文字列だけでなく任意のタイプにすることができ、非 UTF8 文字列もサポートされます。

CBOR

CBOR は、Concise Binary Object Representation の略です。同様に、JSON データ モデルをサポートします。 CBOR は Protobuf や MessagePack ほど有名ではありませんが、次の 2 つの理由で興味深いものです。

    これは公式のインターネット標準です: RFC 7049。
  1. これは、モノのインターネット (IoT) 向けに設計されています。
どうやって選べばいいの?

これは大きな問題です。選択肢がたくさんありますが、どうやって選びますか?考慮すべきさまざまな要素を検討してみましょう:

    シリアル化形式は人間が読める形式、および/または人間が編集できる形式にする必要がありますか?
  1. シリアル化されたコンテンツは信頼できないソースから受信されますか?
  2. シリアル化/逆シリアル化はパフォーマンスのボトルネックですか?
  3. シリアル化されたデータは Python 以外の環境と交換する必要がありますか?
非常に簡単に説明し、いくつかの一般的なシナリオと、それぞれに推奨する形式について説明します。

Python プログラムのローカル状態を自動的に保存する

ここでは pickle (cPickle) と

HIGHEST_PROTOCOL を使用します。高速かつ効率的で、特別なコードを必要とせずにほとんどの Python オブジェクトを保存およびロードできます。ローカル永続キャッシュとしても使用できます。

設定ファイル

間違いなく YAML です。人間が読んだり編集したりする必要があるものにとって、そのシンプルさに勝るものはありません。 Ansible や他の多くのプロジェクトで使用されて成功しています。場合によっては、直接 Python モジュールを構成ファイルとして使用した方がよい場合があります。これは正しい選択かもしれませんが、シリアル化ではなく、実際にはプログラムの一部であり、別個の構成ファイルではありません。

ウェブ API

ここでは

JSON が明らかに勝者です。現在、Web API は、JSON をネイティブに使用する JavaScript Web アプリケーションで最も一般的に使用されています。一部の Web API は他の形式 (たとえば、密な表形式の結果セットの csv) を返す場合がありますが、最小限のオーバーヘッドで CSV データを JSON にパックできると思います (すべての列名を持つオブジェクトとして各行を繰り返す必要はありません)。

大容量・低遅延の大規模通信

バイナリ プロトコルのいずれかを使用します: Protobuf (アーキテクチャが必要な場合)、MessagePack、または CBOR。独自のテストを実行して、各オプションのパフォーマンスと表現機能を検証します。

###結論は###

Python オブジェクトのシリアル化と逆シリアル化は、分散システムの重要な側面です。 Python オブジェクトをネットワーク経由で直接送信することはできません。多くの場合、他の言語で実装された他のシステムと相互運用する必要があり、プログラムの状態を永続ストレージに保存したい場合もあります。

Python には標準ライブラリにいくつかのシリアル化スキームが付属しており、さらに多くのシリアル化スキームがサードパーティ モジュールとして利用可能です。すべてのオプションとそれぞれの長所と短所を理解することで、状況に最も適した方法を選択できるようになります。

以上がPython オブジェクトのシリアル化と逆シリアル化: パート 2の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。