Pythonシーケンス化モジュール-pickleとjson
42990 ワード
Synopsis:Python言語固有のシーケンス化モジュールはpickleですが、シーケンス化をより汎用的でWeb規格に適合させるにはjsonモジュールを使用します.jsonモジュールのdumps()とloads()関数は非常によく定義されたインタフェースの模範である.使用する場合は、必要なパラメータを1つだけ入力する必要があります.しかし、デフォルトのシーケンス化または逆シーケンス化メカニズムが私たちの要件を満たしていない場合、シーケンス化または逆シーケンス化のルールをカスタマイズするために、より多くのパラメータを入力することができます.インタフェースが簡単で使いやすく、十分な拡張性と柔軟性を実現します.
1. pickle
Pythonプログラムが実行されると、オブジェクトはメモリに存在し、プログラムが終了すると、これらのオブジェクトが消費するメモリはオペレーティングシステムによってすべて回収されます.
1.1 pickle.dumps()
このとき、
1.2 pickle.dump()
1.3 pickle.loads()
前のステップのファイルを
1.4 pickle.load()
2. JSON
Pythonに内蔵された
2.1 json.dumps()
2.2 json.dump()
2.3 json.loads()
2.4 json.load()
2.5 TypeError: Object of type 'User' is not JSON serializable
Python
JSON
dict
object
list
array
str
string
int
number (int)
float
number (real)
True
true
False
false
None
null
しかし、一般的なクラスインスタンス化後のオブジェクトはjsonシーケンス化を使用するとエラーが発生します.
解決方法1:クラス属性をJSONにシーケンス化するだけの
解決策2:クラスインスタンス属性値は一般にそのまま出力されません.この場合、
JSONをクラスインスタンスオブジェクトに逆シーケンス化する場合は、
1. pickle
Pythonプログラムが実行されると、オブジェクトはメモリに存在し、プログラムが終了すると、これらのオブジェクトが消費するメモリはオペレーティングシステムによってすべて回収されます.
pickle
モジュールを使用して、オブジェクトをディスクファイルに保存することができます.このようなオブジェクトをメモリから記憶可能または伝送可能にするプロセスを
と呼びます.シーケンス化後、シーケンス化されたコンテンツをディスクに書き込むか、ネットワークを介して他のマシンに転送することができます.逆に,変数の内容をシーケンス化したオブジェクトからメモリに読み直すことを
(unpickling)と呼ぶ.1.1 pickle.dumps()
pickle.dumps()
メソッドは、任意のオブジェクトを1つのbytes
にシーケンス化し、その後、bytes
をfile-like object
メソッドのopen()
モードで開いているファイル記述子、BytesiOなどのwb
に書き込むことができます.参照:http://www.madmalls.com/blog/post/read-write-files-in-python/#62-bytesio In [1]: import pickle
In [2]: d = {'name': 'wangy', 'age': 18}
In [3]: pickle.dumps(d)
Out[3]: b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x05\x00\x00\x00wangyq\x02X\x03\x00\x00\x00ageq\x03K\x12u.'
In [4]: b = pickle.dumps(d)
In [5]: b
Out[5]: b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x05\x00\x00\x00wangyq\x02X\x03\x00\x00\x00ageq\x03K\x12u.'
In [6]: f = open('/tmp/test.txt', 'xb')
In [7]: f.write(b)
Out[7]: 43
In [8]: f.close()
このとき、
/tmp/test.txt
ファイルが作成され、そのデータは書き込まれたばかりのバイトストリームですが、コンテンツを正常に表示できません.[root@CentOS ~]# file /tmp/test.txt
/tmp/test.txt: 8086 relocatable (Microsoft)
[root@CentOS ~]# cat /tmp/test.txt
}q(XnameqXwangyqXageqKu.[root@CentOS ~]#
1.2 pickle.dump()
pickle.dump()
メソッド
オブジェクトをシーケンス化してfile-like object
に書き込みます.たとえば、open()
メソッドのwb
モードで開いているファイル記述子、BytesIOを使用します.参照:http://www.madmalls.com/blog/post/read-write-files-in-python/#62-bytesio In [1]: import pickle
In [2]: d = {'name': 'wangy', 'age': 18}
In [3]: f = open('/tmp/test2.txt', 'xb')
In [4]: pickle.dump(d, f)
In [5]: f.close()
1.3 pickle.loads()
前のステップのファイルを
rb
モードで開き、bytes
に戻り、pickle.loads()
で前の辞書オブジェクトを逆シーケンス化することができます(コンテンツが同じで、異なるオブジェクトであり、idが異なるだけです):In [1]: import pickle
In [2]: f = open('/tmp/test.txt', 'rb')
In [3]: b = f.read()
In [4]: b
Out[4]: b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x05\x00\x00\x00wangyq\x02X\x03\x00\x00\x00ageq\x03K\x12u.'
In [5]: d = pickle.loads(b)
In [6]: d
Out[6]: {'name': 'wangy', 'age': 18}
In [7]: f.close()
1.4 pickle.load()
pickle.load()
メソッドは、1つのfile-like object
からオブジェクトを直接逆シーケンス化するIn [1]: import pickle
In [2]: f = open('/tmp/test.txt', 'rb')
In [3]: d = pickle.load(f)
In [4]: d
Out[4]: {'name': 'wangy', 'age': 18}
In [5]: f.close()
2. JSON
Pythonに内蔵された
json
モジュールは、非常に完全なPythonオブジェクトからJSONフォーマットへの変換を提供します.2.1 json.dumps()
json.dumps()
メソッドは任意のオブジェクトを1つのstr
にシーケンス化し,内容は標準的なJSONである.その後、このstr
をファイルに書き込むことができます(Web開発時はサーバ側がPythonオブジェクトをJSONにシーケンス化した後、直接応答をクライアントに返すのが一般的です):In [1]: import json
In [2]: d = {'name': 'wangy', 'age': 18}
In [3]: s = json.dumps(d)
In [4]: s
Out[4]: '{"name": "wangy", "age": 18}'
In [5]: type(s)
Out[5]: str
In [6]: f = open('/tmp/test.json', 'w')
In [7]: f.write(s)
Out[7]: 28
In [8]: f.close()
[root@CentOS ~]# cat /tmp/test.json
{"name": "wangy", "age": 18}
2.2 json.dump()
json.dump()
メソッドは、オブジェクトをJSONに直接シーケンス化してfile-like object
に書き込みます.Web開発ではファイルに保存されることは少ないので、あまり使いません.In [1]: import json
In [2]: d = {'name': 'wangy', 'age': 18}
In [3]: f = open('/tmp/test.json', 'w')
In [4]: json.dump(d, f)
In [5]: f.close()
2.3 json.loads()
json.loads()
JSONをPythonオブジェクトに逆シーケンス化し、Web開発中にクライアントから送信されたJSONデータをサーバが受信すると、Pythonではstr
と表示される.In [1]: import json
In [2]: json_str = '{"name": "wangy", "age": 18}'
In [3]: d = json.loads(json_str)
In [4]: d
Out[4]: {'name': 'wangy', 'age': 18}
In [5]: type(d)
Out[5]: dict
2.4 json.load()
json.load()
メソッドは、file-like object
から文字列を読み出してPythonオブジェクトに逆シーケンス化し、Web開発では通常、クライアントからJSONを直接受信するため、あまり使用されません.In [1]: import json
In [2]: f = open('/tmp/test.json', 'r')
In [3]: d = json.load(f)
In [4]: d
Out[4]: {'name': 'wangy', 'age': 18}
2.5 TypeError: Object of type 'User' is not JSON serializable
json.dumps()
は、Pythonに組み込まれている基礎データ型(辞書など)を直接JSONにシーケンス化することができます.Python
JSON
dict
object
list
array
str
string
int
number (int)
float
number (real)
True
true
False
false
None
null
しかし、一般的なクラスインスタンス化後のオブジェクトはjsonシーケンス化を使用するとエラーが発生します.
import json
class User:
def __init__(self, name, age):
self.name = name
self.age = age
u = User('wangy', 18)
print(json.dumps(u))
[root@CentOS ~]# python3 test.py
Traceback (most recent call last):
File "test.py", line 11, in
print(json.dumps(u))
File "/usr/local/python-3.6/lib/python3.6/json/__init__.py", line 231, in dumps
return _default_encoder.encode(obj)
File "/usr/local/python-3.6/lib/python3.6/json/encoder.py", line 199, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/local/python-3.6/lib/python3.6/json/encoder.py", line 257, in iterencode
return _iterencode(o, 0)
File "/usr/local/python-3.6/lib/python3.6/json/encoder.py", line 180, in default
o.__class__.__name__)
TypeError: Object of type 'User' is not JSON serializable
解決方法1:クラス属性をJSONにシーケンス化するだけの
であれば、__dict__
In [1]: import json
In [2]: class User:
...: def __init__(self, name, age):
...: self.name = name
...: self.age = age
...:
In [3]: u = User('wangy', 18)
In [4]: json.dumps(u.__dict__)
Out[4]: '{"name": "wangy", "age": 18}'
In [5]: json.dumps(u, default=lambda obj: obj.__dict__) # default , User
Out[5]: '{"name": "wangy", "age": 18}'
解決策2:クラスインスタンス属性値は一般にそのまま出力されません.この場合、
json.dumps()
のdefault
の値を外部関数として指定します.import json
class User:
def __init__(self, name, age):
self.name = name
self.age = age
def toJSON(self):
data = {'name': self.name, 'age': self.age + 10}
return data
def my_json_encoder(obj):
try:
return obj.toJSON()
except:
return obj.__dict__
u = User('wangy', 18)
print(json.dumps(u, default=my_json_encoder, indent=4))
[root@CentOS ~]# python3 test.py
{
"name": "wangy",
"age": 28
}
JSONをクラスインスタンスオブジェクトに逆シーケンス化する場合は、
json.loads()
メソッドを使用し、object_hook
パラメータ値をカスタム関数として指定します.import json
class User:
def __init__(self, name, age):
self.name = name
self.age = age
def toJSON(self):
data = {'name': self.name, 'age': self.age + 10}
return data
def dict2user(d):
return User(d['name'], d['age'] - 10)
json_str = '{"name": "wangy", "age": 38}'
u2 = json.loads(json_str, object_hook=dict2user)
print(u2.name)
print(u2.age)
[root@CentOS ~]# python3 test.py
wangy
28