Rebuild nanopb_pb2.py and print version numbers on import failure (#733, #742)

When python-protobuf and protoc versions do not match, the most common
error message is "AttributeError: module 'google.protobuf.descriptor' has no attribute '_internal_create_key'".
Attempt to provide more helpful info in this situation.
diff --git a/generator/proto/__init__.py b/generator/proto/__init__.py
index 29153d4..e2e8000 100644
--- a/generator/proto/__init__.py
+++ b/generator/proto/__init__.py
@@ -6,31 +6,45 @@
 
 import pkg_resources
 
-from ._utils import has_grpcio_protoc, invoke_protoc
+from ._utils import has_grpcio_protoc, invoke_protoc, print_versions
 
 dirname = os.path.dirname(__file__)
 protosrc = os.path.join(dirname, "nanopb.proto")
 protodst = os.path.join(dirname, "nanopb_pb2.py")
+rebuild = False
 
 if os.path.isfile(protosrc):
     src_date = os.path.getmtime(protosrc)
     if not os.path.isfile(protodst) or os.path.getmtime(protodst) < src_date:
+        rebuild = True
 
-        cmd = [
-            "protoc",
-            "--python_out={}".format(dirname),
-            protosrc,
-            "-I={}".format(dirname),
-        ]
+if not rebuild:
+    try:
+        from . import nanopb_pb2
+    except AttributeError as e:
+        rebuild = True
+        sys.stderr.write("Failed to import nanopb_pb2.py: " + str(e) + "\n"
+                         "Will automatically attempt to rebuild this.\n"
+                         "Verify that python-protobuf and protoc versions match.\n")
+        print_versions()
 
-        if has_grpcio_protoc():
-            # grpcio-tools has an extra CLI argument
-            # from grpc.tools.protoc __main__ invocation.
-            _builtin_proto_include = pkg_resources.resource_filename('grpc_tools', '_proto')
+if rebuild:
+    cmd = [
+        "protoc",
+        "--python_out={}".format(dirname),
+        protosrc,
+        "-I={}".format(dirname),
+    ]
 
-            cmd.append("-I={}".format(_builtin_proto_include))
-        try:
-            invoke_protoc(argv=cmd)
-        except:
-            sys.stderr.write("Failed to build nanopb_pb2.py: " + ' '.join(cmd) + "\n")
-            raise
+    if has_grpcio_protoc():
+        # grpcio-tools has an extra CLI argument
+        # from grpc.tools.protoc __main__ invocation.
+        _builtin_proto_include = pkg_resources.resource_filename('grpc_tools', '_proto')
+
+        cmd.append("-I={}".format(_builtin_proto_include))
+    try:
+        invoke_protoc(argv=cmd)
+    except:
+        sys.stderr.write("Failed to build nanopb_pb2.py: " + ' '.join(cmd) + "\n")
+        raise
+
diff --git a/generator/proto/_utils.py b/generator/proto/_utils.py
index 7076e9d..bd49537 100644
--- a/generator/proto/_utils.py
+++ b/generator/proto/_utils.py
@@ -1,3 +1,4 @@
+import sys
 import subprocess
 import os.path
 
@@ -41,3 +42,25 @@
         return protoc.main(argv)
     else:
         return subprocess.call(argv)
+
+def print_versions():
+    try:
+        if has_grpcio_protoc():
+            import grpc_tools.protoc
+            sys.stderr.write("Using grpcio-tools protoc from " + grpc_tools.protoc.__file__ + "\n")
+        else:
+            sys.stderr.write("Using protoc from system path\n")
+
+        invoke_protoc(['protoc', '--version'])
+    except Exception as e:
+        sys.stderr.write("Failed to determine protoc version: " + str(e) + "\n")
+
+    try:
+        import google.protobuf
+        sys.stderr.write("Using python-protobuf from " + google.protobuf.__file__ + "\n")
+        sys.stderr.write("Python-protobuf version: " + google.protobuf.__version__ + "\n")
+    except Exception as e:
+        sys.stderr.write("Failed to determine python-protobuf version: " + str(e) + "\n")
+
+if __name__ == '__main__':
+    print_versions()