Для задачи отладки я хотел бы читать / записывать сообщения буфера протокола с динамическим импортом файлов, сгенерированных буферами протокола.
Я занимаюсь разработкой приложения, в котором многие задачи будут обмениваться данными с использованием буфера протокола.AMQP.В настоящее время я работаю над задачей отладки Python, которая должна иметь возможность подключаться к любому каналу и отображать обмен данными.Я хочу избежать какой-либо зависимости между этой задачей и файлами .proto.
Решение основано на следующем принципе: - На этапе разработки файлы .proto компилируются в каталог - Задача отладкидинамически импортирует эти файлы ( _pb2.py) - во время выполнения сообщения AMQP содержат имя сообщения и закодированное сообщение.Задача отладки должна иметь возможность динамически создавать сообщение из его имени и его содержимого.
Решение, которое я нашел, работает, но требует вызова eval ().
def ImportPath(path):
messageFactory = dict()
# Browse directory to find protobuf compiled files
sys.path.append(os.path.join(os.path.dirname(__file__), path))
modulesNames = [f for f in os.listdir(path) if re.match(r'.*_pb2.py', f) ]
# for each file, creatre an entry in the factory
for moduleName in modulesNames:
# remove extension
mod = moduleName[:-3]
print ("Import:" + str(mod))
# import module
module = __import__(mod)
for i in module.DESCRIPTOR.message_types_by_name:
print ("Add:"+str(i)+" to messageFactory")
# Is there a better way to do this ?
messageFactory[i]=eval("module."+i+"()")
return messageFactory
messageFactory = ImportPath('.')
# test case
def PrepareTestCase():
proto = 'syntax = "proto2"; message Person { required string name = 1; required int32 id = 2; optional string email = 3;}'
with open('Person.proto','w') as f:
f.write(proto)
os.system('protoc -I=. --python_out=. Person.proto')
def GenericReader(messageType,message):
msg = messageFactory[messageType]
msg.ParseFromString(message)
fieldnames = [ field.name for field in msg.DESCRIPTOR.fields ]
print("GenericReader("+messageType+")")
for fieldname in fieldnames:
s = fieldname + " : ";
if not msg.HasField(fieldname):
s = s + "(NotSet)"
s = s+str(getattr(msg, fieldname))
print(s)
PrepareTestCase()
msg1 = messageFactory['Person']
msg1.name = bytes('Sir Lancelot the Brave','UTF-8');
msg1.id = 2;
msg1.email = bytes('lancelot@camelot.uk','UTF-8');
message = msg1.SerializeToString()
GenericReader('Person',message)
Есть лилучший способ достичь этого?