The Python files are generated from the prototype by
protoc personv3.proto --python_out=python
When I tried to compile my client (see later), I got the error
I am now using the 3.12.2 version of
AttributeError: module 'google.protobuf.descriptor' has no attribute '_internal_create_key'
protoc. It seems that the version installed in Python 3.6 (version 3.11.2) isn't quite compatable with this. I had to do
to get the versions right.
pip3 uninstall protobuf pip3 install protobuf
The compiler just creates one file. However, it isn't nice to look at, as it uses Python meta-calls to generate classes. However, you can write programs assuming that it has generated standard Python classes.
For the example we use, the classes are
The client creates a
Person and then fills in the fields.
To add a
Name there are two ways:
Name object, assigns its fields and then copy
its value into the
or assign the fields of
For the list of emails,
add() new emails
and fill in the fields of each email.
The client is PersonClient.py:
import socket import fileinput import sys import personv3_pb2 PORT = 2001 if len(sys.argv) < 2: print('Usage: comm hostname') exit(1) host = sys.argv person = personv3_pb2.Person() #name = person.Name() #name.family = 'Newmarch' #name.personal = 'Jan' #person.name.CopyFrom(name) person.name.family = 'Newmarch' person.name.personal = 'Jan' email1 = person.email.add() email1.kind = 'private' email1.address = 'email@example.com' email2 = person.email.add() email2.kind = 'work' email2.address = 'firstname.lastname@example.org' print(person) with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((host, PORT)) s.sendall(person.SerializeToString())
The server listens for client connections and reads the data.
It creates a
Person object and then calls the method
ParseFromStrin() on the (binary) data.
Here the servers just prints the created person and terminates the connection.
The server is PersonServer.py:
# https://realpython.com/python-sockets/#echo-server # sequential server import socket import personv3_pb2 HOST = '' # INADDR_ANY PORT = 2001 with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s: s.bind((HOST, PORT)) s.listen() while True: conn, addr = s.accept() with conn: print('Connected by', addr) while True: data = conn.recv(1024) if not data: print('Disconnecting') break person = personv3_pb2.Person() person.ParseFromString(data) print(person)
Copyright © Jan Newmarch, email@example.com
Based on a work at https://jan.newmarch.name/NetworkProgramming/ .