Index: /issm/trunk-jpl/src/m/coordsystems/epsg2proj.py
===================================================================
--- /issm/trunk-jpl/src/m/coordsystems/epsg2proj.py	(revision 27118)
+++ /issm/trunk-jpl/src/m/coordsystems/epsg2proj.py	(revision 27119)
@@ -2,6 +2,6 @@
 
 
-def epsg2proj(epsg): #{{{
-    """EPSG2PROJ - uses gdalsrsinfo to provide PROJ.4 compatible string 
+def epsg2proj(epsg):  #{{{
+    """EPSG2PROJ - uses gdalsrsinfo to provide PROJ.4 compatible string
     from EPSG code
 
@@ -21,5 +21,5 @@
     #First, get GDAL version
     subproc_args = "gdalsrsinfo --version | awk '{print $2}' | cut -d '.' -f1"
-    subproc = subprocess.Popen(subproc_args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    subproc = subprocess.Popen(subproc_args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
     outs, errs = subproc.communicate()
     if errs != '':
@@ -29,5 +29,5 @@
 
     subproc_args = "gdalsrsinfo epsg:{} | command grep PROJ.4 | tr -d '\n' | sed 's/PROJ.4 : //'".format(epsg)
-    subproc = subprocess.Popen(subproc_args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    subproc = subprocess.Popen(subproc_args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
     outs, errs = subproc.communicate()
     if errs != '':
@@ -35,5 +35,5 @@
 
     if version_major == 1:
-        r = r[1:-1]
+        outs = outs[1:-1]
 
     return outs
Index: /issm/trunk-jpl/src/m/coordsystems/gdaltransform.py
===================================================================
--- /issm/trunk-jpl/src/m/coordsystems/gdaltransform.py	(revision 27118)
+++ /issm/trunk-jpl/src/m/coordsystems/gdaltransform.py	(revision 27119)
@@ -46,5 +46,5 @@
 
     subproc_args = shlex.split("gdaltransform -s_srs '{}' -t_srs '{}'".format(proj_in, proj_out))
-    subproc = subprocess.Popen(subproc_args, bufsize=-1, stdin=file_in, stdout=file_out, stderr=subprocess.PIPE, close_fds=True)
+    subproc = subprocess.Popen(subproc_args, bufsize=-1, stdin=file_in, stdout=file_out, stderr=subprocess.PIPE, close_fds=True, universal_newlines=True)
     outs, errs = subproc.communicate()
     if errs != '':
Index: /issm/trunk-jpl/src/m/mesh/planet/gmsh/gmshplanet.py
===================================================================
--- /issm/trunk-jpl/src/m/mesh/planet/gmsh/gmshplanet.py	(revision 27118)
+++ /issm/trunk-jpl/src/m/mesh/planet/gmsh/gmshplanet.py	(revision 27119)
@@ -1,6 +1,4 @@
 import subprocess
-
 import numpy as np
-
 from MatlabFuncs import *
 from mesh3dsurface import *
@@ -26,8 +24,7 @@
     # Get Gmsh version
     subproc_args = 'gmsh -info 2>&1 | command grep \'Version\' | sed -e \'s/Version[[:blank:]]*:[[:blank:]]//\' | cut -d \'.\' -f1'
-    subproc = subprocess.Popen(subproc_args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    subproc = subprocess.Popen(subproc_args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
     outs, errs = subproc.communicate()
-
-    if ((not isinstance(errs,bytes)) & (errs != '')) or (isinstance(errs,bytes) & (errs.decode() != '')):
+    if ((not isinstance(errs, bytes)) & (errs != '')) or (isinstance(errs, bytes) & (errs.decode() != '')):
         raise Exception('gmshplanet: call to gmsh failed: {}'.format(errs))
     gmshmajorversion = int(outs)
@@ -51,9 +48,9 @@
     #
     # NOTE:
-    # - The default format in Gmsh 3 is "msh2". Rather than conditionally 
-    # modifying our parsing scheme for Gmsh 4, for now, we simply set the 
+    # - The default format in Gmsh 3 is "msh2". Rather than conditionally
+    # modifying our parsing scheme for Gmsh 4, for now, we simply set the
     # 'Mesh.MshFileVersion' option.
-    # - Decreasing the value of the 'Mesh.RandomFactor' option leads to an 
-    # equal number of nodes and elements being produced under macOS and Linux 
+    # - Decreasing the value of the 'Mesh.RandomFactor' option leads to an
+    # equal number of nodes and elements being produced under macOS and Linux
     # at certain resolutions using certain meshing algorithms.
     #
@@ -126,12 +123,18 @@
         for i in range(meshini.numberofelements):
             fid.write('ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g};\n'
-                % (meshini.x[meshini.elements[i, 0]-1], meshini.y[meshini.elements[i, 0]-1], meshini.z[meshini.elements[i, 0]-1],
-                meshini.x[meshini.elements[i, 1]-1], meshini.y[meshini.elements[i, 1]-1], meshini.z[meshini.elements[i, 1]-1],
-                meshini.x[meshini.elements[i, 2]-1], meshini.y[meshini.elements[i, 2]-1], meshini.z[meshini.elements[i, 2]-1],
-                metric[meshini.elements[i, 0]-1], metric[meshini.elements[i, 1]-1], metric[meshini.elements[i, 2]-1]))
+                      % (meshini.x[meshini.elements[i, 0] - 1], meshini.y[meshini.elements[i, 0] - 1], meshini.z[meshini.elements[i, 0] - 1],
+                         meshini.x[meshini.elements[i, 1] - 1], meshini.y[meshini.elements[i, 1] - 1], meshini.z[meshini.elements[i, 1] - 1],
+                         meshini.x[meshini.elements[i, 2] - 1], meshini.y[meshini.elements[i, 2] - 1], meshini.z[meshini.elements[i, 2] - 1],
+                         metric[meshini.elements[i, 0] - 1], metric[meshini.elements[i, 1] - 1], metric[meshini.elements[i, 2] - 1]))
         fid.write('};\n')
         fid.close()
         #}}}
 
+    # Call gmsh
+    #
+    # NOTE: The default format in Gmsh 3 is "msh2". Rather than conditionally
+    #       modifying our parsing scheme for Gmsh 4, for now, we simply set the
+    #       "-format" option.
+    #
     if options.exist('refine'):
         subprocess.call('gmsh -2 sphere.geo -bgm sphere.pos', shell=True)
@@ -187,5 +190,5 @@
     #}}}
 
-    # A little technicality here. The mesh is not exactly on the sphere. We 
+    # A little technicality here. The mesh is not exactly on the sphere. We
     # create lat,long coordiantes, and reproject onto an exact sphere.
     mesh.r = np.sqrt(mesh.x ** 2 + mesh.y ** 2 + mesh.z ** 2)
Index: /issm/trunk-jpl/src/m/solve/waitonlock.py
===================================================================
--- /issm/trunk-jpl/src/m/solve/waitonlock.py	(revision 27118)
+++ /issm/trunk-jpl/src/m/solve/waitonlock.py	(revision 27119)
@@ -11,6 +11,6 @@
     """WAITONLOCK - wait for a file
 
-    This routine will return when a file named 'lockfilename' is written to 
-    disk. Also check for outlog file because it might be written several 
+    This routine will return when a file named 'lockfilename' is written to
+    disk. Also check for outlog file because it might be written several
     seconds after the lock file.
 
@@ -21,5 +21,5 @@
 
     TODO:
-    - Uncomment import of localpfe and check on cluster type once localpfe.py 
+    - Uncomment import of localpfe and check on cluster type once localpfe.py
     has been translated from localpfe.m.
     """
@@ -79,12 +79,13 @@
             sys.stdout.write('\rchecking for job completion (time: {} min {} sec)      '.format(floor(elapsedtime / 60), floor(rem(elapsedtime, 60)))) # TODO: After Python 2 is deprecated, we can change this call to print([...], end='')
             elapsedtime = elapsedtime / 60 # Converts time from sec to min
-            subproc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-            outs, errs = subproc.communicate() # NOTE: Need to consume output before checking return code
+            subproc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
+            outs, errs = subproc.communicate()  # NOTE: Need to consume output before checking return code
 
             # TODO: Debug the following check under Linux (exits after first iteration with errs = "b")
             # UPDATE: Works in testing under Debian Linux system. Leaving comment for now so that it is easier to backtrace this issue if someone else encounters it.
+            # FIXED: comunicates returns stuff in bytes in Python 3 unless you set "universal_newlines=True"
             #
-            #if errs != '':
-            #    raise Exception('waitonlock: check for existence of files failed: {}'.format(errs))
+            if errs != '':
+               raise Exception('waitonlock: check for existence of files failed: {}'.format(errs))
             ispresent = not subproc.returncode
             if ispresent:
