파이썬 함수를 피클 (또는 코드를 직렬화)하는 쉬운 방법이 있습니까?
네트워크 연결을 통해 기능을 전송하려고합니다 (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 모듈 참조 ) 함수 나 메서드의 소스 코드와 함께 문자열을 반환하는 것입니다.
It all depends on whether you generate the function at runtime or not:
If you do - inspect.getsource(object)
won't work for dynamically generated functions as it gets object's source from .py
file, so only functions defined before execution can be retrieved as source.
And if your functions are placed in files anyway, why not give receiver access to them and only pass around module and function names.
The only solution for dynamically created functions that I can think of is to construct function as a string before transmission, transmit source, and then eval()
it on the receiver side.
Edit: the marshal
solution looks also pretty smart, didn't know you can serialize something other thatn built-ins
The cloud
package (pip install cloud) can pickle arbitrary code, including dependencies. See https://stackoverflow.com/a/16891169/1264797.
The basic functions used for this module covers your query, plus you get the best compression over the wire; see the instructive source code:
y_serial.py module :: warehouse Python objects with SQLite
"Serialization + persistance :: in a few lines of code, compress and annotate Python objects into SQLite; then later retrieve them chronologically by keywords without any SQL. Most useful "standard" module for a database to store schema-less data."
http://yserial.sourceforge.net
code_string = ''' def foo(x): return x * 2 def bar(x): return x ** 2 ''' obj = pickle.dumps(code_string)
Now
exec(pickle.loads(obj)) foo(1) > 2 bar(3) > 9
Cloudpickle is probably what you are looking for. Cloudpickle is described as follows:
cloudpickle is especially useful for cluster computing where Python code is shipped over the network to execute on remote hosts, possibly close to the data.
Usage example:
def add_one(n):
return n + 1
pickled_function = cloudpickle.dumps(add_one)
pickle.loads(pickled_function)(42)
'code' 카테고리의 다른 글
TensorFlow 저장 / 파일에서 그래프로드 (0) | 2020.09.06 |
---|---|
AsQueryable ()의 목적은 무엇입니까? (0) | 2020.09.06 |
Linux 명령 : 텍스트 파일 만 '찾기'방법은 무엇입니까? (0) | 2020.09.05 |
Jquery 바인딩 두 번 클릭과 단일 클릭을 별도로 (0) | 2020.09.05 |
R의 문자열에서 모든 특수 문자를 제거 하시겠습니까? (0) | 2020.09.05 |