답변:
함수 바이트 코드를 직렬화 한 다음 호출자에서 재구성 할 수 있습니다. 정렬 화 모듈은 다음의 함수로 재 조립 될 수 직렬화를 코드 오브젝트로 사용할 수있다. 즉 :
import marshal
def foo(x): return x*x
code_string = marshal.dumps(foo.func_code)
그런 다음 원격 프로세스에서 (code_string 전송 후) :
import marshal, types
code = marshal.loads(code_string)
func = types.FunctionType(code, globals(), "some_func_name")
func(10) # gives 100
몇 가지주의 사항 :
marshal의 형식 (해당 문제에 대한 모든 파이썬 바이트 코드)은 주요 파이썬 버전간에 호환되지 않을 수 있습니다.
cpython 구현에서만 작동합니다.
함수가 선택해야하는 전역 (가져온 모듈, 기타 함수 등 포함)을 참조하는 경우 이들도 직렬화하거나 원격 측에서 다시 만들어야합니다. 내 예제는 원격 프로세스의 전역 네임 스페이스를 제공합니다.
클로저 또는 생성기 함수와 같은 더 복잡한 경우를 지원하려면 더 많은 작업을 수행해야 할 것입니다.
marshal
초기화 된 사전 사전을 직렬화하는 모듈 을 적용하려고합니다 defaultdict(lambda : defaultdict(int))
. 그러나 그것은 오류를 반환합니다 ValueError: unmarshallable object
. 참고 저는 python2.7을 사용하고 있습니다. 어떤 생각? 감사합니다
foo.func_code
발생합니다 AttributeError
. 기능 코드를 얻는 다른 방법이 있습니까?
Python의 pickle 라이브러리를 확장하여 함수를 포함한 다양한 유형을 지원하는 Dill을 확인하십시오 .
>>> import dill as pickle
>>> def f(x): return x + 1
...
>>> g = pickle.dumps(f)
>>> f(1)
2
>>> pickle.loads(g)(1)
2
또한 함수의 클로저에서 객체에 대한 참조를 지원합니다.
>>> def plusTwo(x): return f(f(x))
...
>>> pickle.loads(pickle.dumps(plusTwo))(1)
3
가장 간단한 방법은 아마도 inspect.getsource(object)
( inspect 모듈 참조 ) 함수 나 메서드의 소스 코드와 함께 문자열을 반환하는 것입니다.
그것은 모두 런타임에 함수를 생성하는지 여부에 달려 있습니다.
그렇게하면- 파일 inspect.getsource(object)
에서 객체의 소스를 가져 오므로 동적으로 생성 된 함수에 대해 작동하지 않으므로 .py
실행 전에 정의 된 함수 만 소스로 검색 할 수 있습니다.
어쨌든 함수가 파일에 배치되어 있다면 수신기 액세스 권한을 부여하고 모듈 및 함수 이름 만 전달하십시오.
내가 생각할 수있는 동적으로 생성 된 함수에 대한 유일한 해결책은 전송 전에 문자열로 함수를 구성하고 소스를 전송 한 다음 eval()
수신기 측에서 함수를 구성하는 것입니다 .
편집 : marshal
솔루션도 꽤 똑똑해 보이며 내장 된 다른 것을 직렬화 할 수 있다는 것을 몰랐습니다.
cloud
패키지 (클라우드를 설치 PIP) 의존성을 포함하여 임의의 코드를, 피클 수 있습니다. https://stackoverflow.com/a/16891169/1264797을 참조 하십시오 .
code_string = '' ' def foo (x) : 반환 x * 2 데프 바 (x) : 반환 x ** 2 '' ' obj = pickle.dumps (코드 _ 문자열)
지금
exec (pickle.loads (obj)) foo (1) > 2 바 (3) > 9
이 모듈에 사용되는 기본 기능은 쿼리를 다루고 유선을 통해 최상의 압축을 얻을 수 있습니다. 유익한 소스 코드를 참조하십시오.
y_serial.py 모듈 :: SQLite로 Python 객체웨어 하우스
"Serialization + persistance :: 몇 줄의 코드로 Python 객체를 SQLite로 압축하고 주석을 단 다음 나중에 SQL없이 키워드로 시간순으로 검색합니다. 데이터베이스가 스키마없는 데이터를 저장하는 데 가장 유용한"표준 "모듈입니다."
Cloudpickle 은 아마도 당신이 찾고있는 것일 것입니다. Cloudpickle은 다음과 같이 설명됩니다.
cloudpickle은 데이터에 가까운 원격 호스트에서 실행하기 위해 Python 코드가 네트워크를 통해 제공되는 클러스터 컴퓨팅에 특히 유용합니다.
사용 예 :
def add_one(n):
return n + 1
pickled_function = cloudpickle.dumps(add_one)
pickle.loads(pickled_function)(42)
다음은 함수를 피클 가능하게 만들기 위해 래핑하는 데 사용할 수있는 도우미 클래스입니다. 이미 언급 된주의 사항 marshal
이 적용되지만 가능할 때마다 피클을 사용하도록 노력하고 있습니다. 직렬화에서 전역 또는 클로저를 보존하려는 노력은 없습니다.
class PicklableFunction:
def __init__(self, fun):
self._fun = fun
def __call__(self, *args, **kwargs):
return self._fun(*args, **kwargs)
def __getstate__(self):
try:
return pickle.dumps(self._fun)
except Exception:
return marshal.dumps((self._fun.__code__, self._fun.__name__))
def __setstate__(self, state):
try:
self._fun = pickle.loads(state)
except Exception:
code, name = marshal.loads(state)
self._fun = types.FunctionType(code, {}, name)