2017-05-05 3 views
0

나는 pickle을 compile/exec에 사용하고 싶지만 저에게는 적합하지 않습니다. 전역 네임 스페이스를 사용할 때만 작동합니다. 하지만 글로벌 네임 스페이스를 사용하고 싶지는 않습니다. 감사합니다컴파일/exec에서 pickle이 작동하지 않습니다.

>>> a = compile("def f():\n\t'hello'\nimport pickle\npickle.dumps(f)", "<stdin>", "exec") 
>>> exec(a)   # works 
>>> exec(a, {})  # fails 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 4, in <module> 
_pickle.PicklingError: Can't pickle <function f at 0x1050881e0>: it's not the same object as __main__.f 
>>> exec(a, {'__name__': '__main__'}) # fails too 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 4, in <module> 
_pickle.PicklingError: Can't pickle <function f at 0x1050882f0>: it's not the same object as __main__.f 
+0

'dill' 피클 기능이 있어야 작동 할 수 있습니다. – tdelaney

+0

@tdelaney 죄송합니다. 이해가 가지 않습니다. 더 설명해 주시겠습니까? Thanks – zjffdu

+0

'pickle'은 함수의 텍스트 이름은 저장하지만 함수 객체는 저장하지 않습니다. unpickler는 함수를 가져 오기 위해 모듈을 가져와야합니다. 첫 번째 경우에는 함수를 최상위 스크립트의 전역 네임 스페이스에 바인딩했습니다. 그 네임 스페이스는'__main__'이라고 불리 웠으므로'__main__' 모듈을로드하고'f' 함수를 사용하기 만하면됩니다. '__main__'도'f'도 찾을 수 없으므로 작동하지 않습니다. '딜 (dill)'은 기능 자체를 피클하고 당신을 위해 일할 수있는 기회가 더 많습니다. – tdelaney

답변

1

아니요, 아무 것도 어쨌든 합리적이지 않습니다. 함수는 정규화 된 이름으로 피클 링하며 실제로 구현의 일부를 피킹하지 않습니다. 모듈은 정의 된 모듈을 가져 와서 문제의 이름을로드하기 만하면됩니다. 해당 함수를 찾을 네임 스페이스가없는 경우 (__main__의 전역을 __main__의 전역과 연결되지 않은 사용자 지정 dict으로 바꾼 경우 __main__.f (정규화 된 이름은 f)이 아니기 때문에 이 아니기 때문에 pickle이 될 수 없습니다 __main__의 전역에 존재하지 않습니다.

+0

어쨌든 컴파일/exec에서 모듈을 정의 할 수 있습니까? – zjffdu

+0

@zjffdu : 가져온 모듈의 전역 변수를'exec'에 넘겨 주면 정의 된 것처럼 동작합니다. 예를 들어,'import os'와 같이,''exec (a, vars (os))'는'os.' 모듈에'fs.'가 실제로 정의되기 때문에 작동 할 것입니다. 그래서 그것은 절인 될 수있다 ('fs '라는 이름의 함수를'os' 모듈에 붙이지 않은 사람은 그것을 언 패킹 할 수 없다). – ShadowRanger

관련 문제