import os
import sys
import grpc
class CustomModule:
def __init__(self, name, server_info, proto_files,):
# proto_file: one folder, includes proto file name + proto file content
self.name = name
self.server_info = server_info
self.proto_files = proto_files
def register(self):
bin_path = os.path.join("services", os.path.dirname(self.proto_files[0]['name']))
proto_path = os.path.join("services", "protos", os.path.dirname(self.proto_files[0]['name']))
if not os.path.exists(proto_path) :
os.makedirs(proto_path)
if not os.path.exists(bin_path):
os.makedirs(bin_path)
for file in self.proto_files:
proto_file = os.path.join(proto_path, os.path.basename(file['name']))
with open(proto_file, 'wb') as fw:
fw.write(file['content'])
# Run shell command
command = f'python -m grpc_tools.protoc -I {proto_path} --python_out={bin_path} --grpc_python_out={bin_path} {proto_path}/*.proto'
os.system(command)
# def get_package(self):
# package = []
# for file in os.listdir(os.path.join('services', os.path.dirname(self.proto_files[0]['name']))):
# filename, ext = os.path.splitext(file)
# package.append(filename)
# return package
def check_param_type(self, param_type_str):
sys.path.append(
os.path.join(os.path.dirname(__file__), 'services', os.path.dirname(self.proto_files[0]['name'])))
for file in os.listdir(os.path.join('services', os.path.dirname(self.proto_files[0]['name']))):
filename, ext = os.path.splitext(file)
type_class = None
type_matches = False
try:
package = __import__(filename)
type_class = getattr(package, param_type_str)
type_matches = True
break
except Exception as ex:
continue
if not type_matches:
print(f"No type matches for type: {param_type_str}")
exit(-1)
return type_class
def run(self, run_service, run_method, input_param_type, input_param_value, response_type):
# print(f"Execute node : {self.name}")
input_class = self.check_param_type(input_param_type)
response_class = self.check_param_type(response_type)
input_instance = input_class()
input_instance.ParseFromString(input_param_value)
restful_api = f"/{run_service}/{run_method}"
with grpc.insecure_channel(self.server_info) as channel:
func = channel.unary_unary(
restful_api,
request_serializer = getattr(input_class, 'SerializeToString' ),
response_deserializer=getattr(response_class, 'FromString' ),
# request_serializer=pb_event.User.SerializeToString,
# response_deserializer=pb_event.FileSet.FromString,
)
response = func(input_instance)
print(response)
if __name__ == "__main__":
model = CustomModule('test_journal','localhost:50052', [{'name': 'journal/journal_data.proto', 'content': open('/home/lc/PycharmProjects/python/my_travel/ai_learning/protos/journal_data.proto', 'rb').read()},
{'name': 'journal/journal_event.proto', 'content': open('/home/lc/PycharmProjects/python/my_travel/ai_learning/protos/journal_event.proto', 'rb').read()}])
model.register()
# print(model.get_package())
# print(model.check_param_type('User'))
# print(model.check_param_type('FileSet'))
curpath = os.path.dirname(__file__)
sys.path.append(os.path.join(curpath, 'services', 'journal'))
import journal_event_pb2 as pb_event
user = pb_event.User(username='lc-host')
model.run(run_service='JournalEvents', run_method='GetFileMetas', input_param_type='User', input_param_value=user.SerializeToString(), response_type='FileSet')
1. 首先在页面通过注册要调用的服务, 包含地址:接口,服务名称,以及相应的proto files (主要是为了得到传输过程中的数据类型)
2. 注册时会将proto file读入本地,然后调用 proto generation 生成 pb文件
3. 注册模块之后就可以使用这个service下的所有方法,方法通过名字传入,输入参数的类型通过法序列化得到;
4.执行的时候就是调用grpc channel stub 执行相应的方法