네트워크 연결을 통해 기능을 전송하려고합니다 (asyncore 사용). 이와 같은 전송을 위해 Python 함수 (이 경우 적어도 부작용이없는 함수)를 직렬화하는 쉬운 방법이 있습니까?
이상적으로는 다음과 같은 한 쌍의 기능을 갖고 싶습니다.
def transmit(func):
obj = pickle.dumps(func)
[send obj across the network]
def receive():
[receive obj from the network]
func = pickle.loads(s)
func()
답변
함수 바이트 코드를 직렬화 한 다음 호출자에서 재구성 할 수 있습니다. 정렬 화 모듈은 다음의 함수로 재 조립 될 수 직렬화를 코드 오브젝트로 사용할 수있다. 즉 :
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 구현에서만 작동합니다.
-
함수가 선택해야하는 전역 (가져온 모듈, 기타 함수 등 포함)을 참조하는 경우 이들도 직렬화하거나 원격 측에서 다시 만들어야합니다. 내 예제는 원격 프로세스의 전역 네임 스페이스를 제공합니다.
-
클로저 또는 생성기 함수와 같은 더 복잡한 경우를 지원하려면 더 많은 작업을 수행해야 할 것입니다.
답변
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