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
AttributeError: module 'google.protobuf.descriptor' has no attribute '_internal_create_key'
I am now using the 3.12.2 version of 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
pip3 uninstall protobuf
pip3 install protobuf
to get the versions right.
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 Person
,
Person.Name
and Person.Email
.
The client creates a Person
and then fills in the fields.
To add a Name
there are two ways:
create a Name
object, assigns its fields and then copy
its value into the Person.Name
by
CopyFrom()
,
or assign the fields of Person.Name
directly.
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[1]
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 = 'jan@newmarch.name'
email2 = person.email.add()
email2.kind = 'work'
email2.address = 'j.newmarch@boxhill.edu.au'
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, jan@newmarch.name
" Network Programming using Java, Go, Python, Rust, JavaScript and Julia"
by
Jan Newmarch
is licensed under a
Creative Commons Attribution-ShareAlike 4.0 International License
.
Based on a work at
https://jan.newmarch.name/NetworkProgramming/
.