필자는 동적으로 생성 된 유형 (즉, 3-arg type()
을 호출하여 생성 된 유형)을 피클 링하고 멋지게 제거하려고 시도했습니다. 난 this module switching trick 모듈의 사용자로부터 세부 정보를 숨기고 깨끗한 의미를 부여하기 위해 사용 해왔다. 이미동적으로 생성 된 피킹
내가 배운 몇 가지 :
이- 유형이 유형은 무엇
getattr
발견과 일치해야합니다 - 모듈 자체에
getattr
로 검색 가능해야합니다, 그것은 우리가pickle.dumps(o)
를 호출하면 말을하는 것입니다 다음은 그래도 붙어있어type(o) == getattr(module, 'name of type')
여전히 뭔가 이상한 일이있을 것 같은 것을 참이어야합니다 - 그것은 __getstate__
를 호출하는 것으로 보인다 예기치 않은 일에.
다음은 파이썬 3.5 시험 문제를 재현 내가있어 간단한 설치, 그러나 나는 가능하면 3.3로 다시 타겟팅 할 : 다음
# module.py
import sys
import functools
def dump(self):
return b'Some data' # Dummy for testing
def undump(self, data):
print('Undump: %r' % data) # Do nothing for testing
# Cheaty demo way to make this consistent
@functools.lru_cache(maxsize=None)
def make_type(name):
return type(name,(), {
'__getstate__': dump,
'__setstate__': undump,
})
class Magic(object):
def __init__(self, path):
self.path = path
def __getattr__(self, name):
print('Getting thing: %s (from: %s)' % (name, self.path))
# for simple testing all calls to make_type must end in last x.y.z.last
if name != 'last':
if self.path:
return Magic(self.path + '.' + name)
else:
return Magic(name)
return make_type(self.path + '.' + name)
# Make the switch
sys.modules[__name__] = Magic('')
그리고 빠른 방법이 운동을 :
import module
import pickle
f=module.foo.bar.woof.last()
print(f.__getstate__()) # See, *this* works
print('Pickle starts here')
print(pickle.dumps(f))
다음주는 : 난 아무것도가 0123보고보고 기대하지 않은
Getting thing: foo (from:)
Getting thing: bar (from: foo)
Getting thing: woof (from: foo.bar)
Getting thing: last (from: foo.bar.woof)
b'Some data'
Pickle starts here
Getting thing: __spec__ (from:)
Getting thing: _initializing (from: __spec__)
Getting thing: foo (from:)
Getting thing: bar (from: foo)
Getting thing: woof (from: foo.bar)
Getting thing: last (from: foo.bar.woof)
Getting thing: __getstate__ (from: foo.bar.woof)
Traceback (most recent call last):
File "test.py", line 7, in <module>
print(pickle.dumps(f))
TypeError: 'Magic' object is not callable
module.foo.bar.woof
에,하지만 우리는 추가하여 실패하는 조회를 강제하더라도 :에
if name == '__getstate__': raise AttributeError()
우리 __getattr__
여전히 실패 :
Traceback (most recent call last):
File "test.py", line 7, in <module>
print(pickle.dumps(f))
_pickle.PicklingError: Can't pickle <class 'module.Magic'>: it's not the same object as module.Magic
은 무엇을 주는가? __spec__
으로 누락 된 것이 있습니까? docs for __spec__
꽤 많은 스트레스가 적절하게 설정되어 있지만 실제로 많은 것을 설명하지는 않습니다.
더 중요한 질문은 의사 모듈 __getattr__
구현 피클을 통해 프로그래밍 방식으로 생성 된 유형을 만드는 것에 대해 어떻게 생각해야할까요?
는 f
의 클래스 module.foo.bar.woof.last
피클을
모듈 전환 트릭을 사용해야하는 이유가 있습니까? 귀하의 예제를 좀 더 단순화 시켰고'module.Magic (''). foo.bar.woof.last()'와 잘 동작합니다. 모듈 스위치는'it is not same object' 에러를 발생시킵니다. 나는 아직도 이러한 모든 문제를 일으키는 세부 사항을 연구 중이다. – illiteratecoder