Accéder champ de Protobuf message de type inconnu en Python
Disons que j'ai 2 Protobuf-Messages, A et B. l'ensemble de Leur structure est similaire, mais pas identique. Nous sommes donc partagés choses dans un autre message, que nous avons appelé des Communes. Cela fonctionne à merveille.
Cependant, je suis maintenant face au problème suivant: Un cas particulier existe où je dois traiter un message avec numéro de série, mais je ne sais pas si c'est un message de type A ou de type B. j'ai une solution qui fonctionne en C++ (voir ci-dessous), mais je n'ai pas réussi à trouver un moyen de faire la même chose en Python.
Exemple:
//file: Common.proto
//contains some kind of shared struct that is used by all messages:
message Common {
...
}
//file: A.proto
import "Common.proto";
message A {
required int32 FormatVersion = 1;
optional bool SomeFlag [default = true] = 2;
optional Common CommonSettings = 3;
... A-specific Fields ...
}
//file: B.proto
import "Common.proto";
message B {
required int32 FormatVersion = 1;
optional bool SomeFlag [default = true] = 2;
optional Common CommonSettings = 3;
... B-specific Fields ...
}
Solution de travail en C++
En C++, je suis en utilisant l'API reflection pour obtenir l'accès à la CommonSettings champ comme ceci:
namespace gp = google::protobuf;
...
Common* getCommonBlock(gp::Message* paMessage)
{
gp::Message* paMessage = new gp::Message();
gp::FieldDescriptor* paFieldDescriptor = paMessage->GetDescriptor()->FindFieldByNumber(3);
gp::Reflection* paReflection = paMessage->GetReflection();
return dynamic_cast<Common&>(paReflection->GetMessage(*paMessage,paFieldDescriptor));
}
La méthode 'getCommonBlock' utilise FindFieldByNumber() pour obtenir le descripteur de champ que j'essaie de faire. Ensuite, il utilise la réflexion pour récupérer les données réelles. getCommonBlock peut traiter des messages de type A, B ou dans tout autre type de longtemps que le champ Commun demeure située à l'indice 3.
Ma Question est: Est-il un moyen de faire quelque chose de similaire Python? J'ai été à la recherche à la Protobuf documentation, mais ne pouvait pas trouver un moyen de le faire.
OriginalL'auteur djf | 2013-05-17
Vous devez vous connecter pour publier un commentaire.
Je sais que c'est un vieux thread, mais je vais répondre quand même pour la postérité:
Tout d'abord, comme vous le savez, il n'est pas possible de déterminer le type de protocole de la mémoire tampon de message uniquement à partir de sa forme sérialisée. La seule information dans la forme sérialisée vous avez accès à est le domaine des nombres et de leurs valeurs sérialisées.
Deuxièmement, la "bonne" façon de le faire serait d'avoir un proto qui contient à la fois, comme
De cette façon, il n'y a pas d'ambiguïté: il vous suffit d'analyser le même proto (
Parent
) à chaque fois.De toute façon, si il est trop tard pour changer les choses, ce que je vous recommande de faire est de définir un nouveau message avec uniquement les champs de partagée, comme
Vous devriez alors être en mesure de prétendre que le message (
A
ouB
) est en fait unShared
, et de l'analyser en conséquence. L'inconnu champs ne sera pas pertinente.OriginalL'auteur Robert Martin
Un des avantages de Python sur une statiquement typé des langages comme le C++, c'est que vous n'avez pas besoin d'utiliser toute spéciale code de réflexion pour obtenir un attribut d'un objet de type inconnu: il vous suffit de demander à l'objet. La fonction intégrée qui ne c'est
getattr
, de sorte que vous pouvez faire:OriginalL'auteur Daniel Roseman
J'ai eu un problème similaire.
Ce que j'ai fait était de créer un nouveau message, avec un enum spécifiant le type:
Puis de créer des types de message:
Et:
Assurez-vous de définir correctement la "Base" du message, ou vous ne serez pas compatible binaire si vous ajoutez des champs dernièrement (comme vous avez de maj hériter message champs de trop).
De cette façon, vous pouvez recevoir un message générique:
Espère que cette aide.
Si vous avez importé correctement, ce TYPE est un enum définis dans le protobuf fichier de sorte que vous êtes en mesure de les appeler directement.
OriginalL'auteur kraptor
Comment à propos de "concaténation" deux tampons de protocole dans un en-tête+format de charge utile, par exemple, l'en-tête pour le commun des données suivantes par message A ou B, comme suggéré par protobuf techniques?
C'est la façon dont je l'ai fait avec différents types de charge utile en tant que blob dans mqtt message.
OriginalL'auteur deddebme