Skip to content

Commit 26c58b3

Browse files
authored
docs: add python sdk manual (#3056)
1 parent de52c77 commit 26c58b3

File tree

12 files changed

+1109
-47
lines changed

12 files changed

+1109
-47
lines changed

content/en/overview/mannual/_index.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,16 @@ weight: 6
7676
</div>
7777
</div>
7878
</div>
79+
<div class="col-sm col-md-6 mb-4">
80+
<div class="h-100 card shadow">
81+
<div class="card-body">
82+
<h4 class="card-title">
83+
<a href='{{< relref "./python-sdk" >}}'>Python SDK</a>
84+
</h4>
85+
<p>Dubbo Python SDK Manual</p>
86+
</div>
87+
</div>
88+
</div>
7989
</div>
8090
<hr>
8191
</div>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
aliases:
3+
- /en/docs3-v2/python-sdk/
4+
description: Python SDK Manual
5+
linkTitle: Python SDK
6+
title: Python SDK
7+
type: docs
8+
weight: 5
9+
---
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
---
2+
aliases:
3+
- /en/docs3-v2/python-sdk/custom-serialization/
4+
description: Dubbo Python Custom Serialization
5+
linkTitle: Custom Serialization
6+
title: Custom Serialization
7+
type: docs
8+
weight: 2
9+
---
10+
11+
See the full [example here](https://github.com/apache/dubbo-python/tree/main/samples/serialization)
12+
13+
Python is a dynamic language, and its flexibility makes it challenging to design a universal serialization layer as seen in other languages. Therefore, we have removed the "serialization layer" and left it to the users to implement (since users know the formats of the data they will pass).
14+
15+
Serialization typically consists of two parts: serialization and deserialization. We have defined the types for these functions, and custom serialization/deserialization functions must adhere to these "formats."
16+
17+
18+
19+
First, for serialization functions, we specify:
20+
21+
```python
22+
# A function that takes an argument of any type and returns data of type bytes
23+
SerializingFunction = Callable[[Any], bytes]
24+
```
25+
26+
Next, for deserialization functions, we specify:
27+
28+
```python
29+
# A function that takes an argument of type bytes and returns data of any type
30+
DeserializingFunction = Callable[[bytes], Any]
31+
```
32+
33+
Below, I'll demonstrate how to use custom functions with `protobuf` and `json`.
34+
35+
36+
37+
### protobuf
38+
39+
1. For defining and compiling `protobuf` files, please refer to the [protobuf tutorial](https://protobuf.dev/getting-started/pythontutorial/) for detailed instructions.
40+
41+
2. Set `xxx_serializer` and `xxx_deserializer` in the client and server.
42+
43+
client
44+
45+
```python
46+
class GreeterServiceStub:
47+
def __init__(self, client: dubbo.Client):
48+
self.unary = client.unary(
49+
method_name="sayHello",
50+
request_serializer=greeter_pb2.GreeterRequest.SerializeToString,
51+
response_deserializer=greeter_pb2.GreeterReply.FromString,
52+
)
53+
54+
def say_hello(self, request):
55+
return self.unary(request)
56+
57+
58+
if __name__ == "__main__":
59+
reference_config = ReferenceConfig.from_url(
60+
"tri://127.0.0.1:50051/org.apache.dubbo.samples.proto.Greeter"
61+
)
62+
dubbo_client = dubbo.Client(reference_config)
63+
64+
stub = GreeterServiceStub(dubbo_client)
65+
result = stub.say_hello(greeter_pb2.GreeterRequest(name="hello"))
66+
print(result.message)
67+
```
68+
69+
server
70+
71+
```python
72+
def say_hello(request):
73+
print(f"Received request: {request}")
74+
return greeter_pb2.GreeterReply(message=f"{request.name} Dubbo!")
75+
76+
77+
if __name__ == "__main__":
78+
# build a method handler
79+
method_handler = RpcMethodHandler.unary(
80+
say_hello,
81+
request_deserializer=greeter_pb2.GreeterRequest.FromString,
82+
response_serializer=greeter_pb2.GreeterReply.SerializeToString,
83+
)
84+
# build a service handler
85+
service_handler = RpcServiceHandler(
86+
service_name="org.apache.dubbo.samples.proto.Greeter",
87+
method_handlers={"sayHello": method_handler},
88+
)
89+
90+
service_config = ServiceConfig(service_handler)
91+
92+
# start the server
93+
server = dubbo.Server(service_config).start()
94+
95+
input("Press Enter to stop the server...\n")
96+
```
97+
98+
99+
100+
### Json
101+
102+
`protobuf` does not fully illustrate how to implement custom serialization and deserialization because its built-in functions perfectly meet the requirements. Instead, I'll demonstrate how to create custom serialization and deserialization functions using `orjson`:
103+
104+
1. Install `orjson`:
105+
106+
```shell
107+
pip install orjson
108+
```
109+
110+
2. Define serialization and deserialization functions:
111+
112+
client
113+
114+
```python
115+
def request_serializer(data: Dict) -> bytes:
116+
return orjson.dumps(data)
117+
118+
119+
def response_deserializer(data: bytes) -> Dict:
120+
return orjson.loads(data)
121+
122+
123+
class GreeterServiceStub:
124+
def __init__(self, client: dubbo.Client):
125+
self.unary = client.unary(
126+
method_name="unary",
127+
request_serializer=request_serializer,
128+
response_deserializer=response_deserializer,
129+
)
130+
131+
def say_hello(self, request):
132+
return self.unary(request)
133+
134+
135+
if __name__ == "__main__":
136+
reference_config = ReferenceConfig.from_url(
137+
"tri://127.0.0.1:50051/org.apache.dubbo.samples.serialization.json"
138+
)
139+
dubbo_client = dubbo.Client(reference_config)
140+
141+
stub = GreeterServiceStub(dubbo_client)
142+
result = stub.say_hello({"name": "world"})
143+
print(result)
144+
```
145+
146+
server
147+
148+
```python
149+
def request_deserializer(data: bytes) -> Dict:
150+
return orjson.loads(data)
151+
152+
153+
def response_serializer(data: Dict) -> bytes:
154+
return orjson.dumps(data)
155+
156+
157+
def handle_unary(request):
158+
print(f"Received request: {request}")
159+
return {"message": f"Hello, {request['name']}"}
160+
161+
162+
if __name__ == "__main__":
163+
# build a method handler
164+
method_handler = RpcMethodHandler.unary(
165+
handle_unary,
166+
request_deserializer=request_deserializer,
167+
response_serializer=response_serializer,
168+
)
169+
# build a service handler
170+
service_handler = RpcServiceHandler(
171+
service_name="org.apache.dubbo.samples.HelloWorld",
172+
method_handlers={"unary": method_handler},
173+
)
174+
175+
service_config = ServiceConfig(service_handler)
176+
177+
# start the server
178+
server = dubbo.Server(service_config).start()
179+
180+
input("Press Enter to stop the server...\n")
181+
```
182+
183+

0 commit comments

Comments
 (0)