# HG changeset patch
# User Nathan Kohagen <nathankohagen@gmail.com>
# Date 1661239397 25200
#      Tue Aug 23 00:23:17 2022 -0700
# Branch py3
# Node ID ee795c6445861e6d8c3369140d957a255874be10
# Parent  5da559ffde25fce67373ac65814e3edbba37f409
2to3 fixes; no intended change to functional behavior; fixes #10001

tested with Baofeng BF-F8HP ;
fixed warnings and errors from other radio code observed at program start ;
summary of changes approximately sorted from most common to least common:
*  python2's print keyword replaced with python3's print() function;
*  from __future__ import print_function #python2 compatibility
*  exception syntax; s/except Exception, e:/except Exception as e:/
*  replace xrange() with range() ; s/xrange/range/
*  python3 expects explicit relative imports
*  python2's implicit integer division results in type mismatches and
  should be replaced with // operator or __floordiv__
*  list(range(...)) in some places because range() produces iterator
*  string UTF-8 encode for concatenation of string to bytes
*  s/string.uppercase/string.ascii_uppercase/
*  python3 removed Tuple Parameter Unpacking

diff --git a/chirp/drivers/alinco.py b/chirp/drivers/alinco.py
--- a/chirp/drivers/alinco.py
+++ b/chirp/drivers/alinco.py
@@ -199,7 +199,7 @@
             self._mmap = self._download(self._memsize)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
         self.process_mmap()
 
@@ -208,7 +208,7 @@
             self._upload(self._memsize)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
 
     def get_raw_memory(self, number):
diff --git a/chirp/drivers/anytone.py b/chirp/drivers/anytone.py
--- a/chirp/drivers/anytone.py
+++ b/chirp/drivers/anytone.py
@@ -177,7 +177,7 @@
     try:
         radio.pipe.write(data)
         radio.pipe.read(len(data))
-    except Exception, e:
+    except Exception as e:
         LOG.error("Error writing to radio: %s" % e)
         raise errors.RadioError("Unable to write to radio")
 
@@ -185,7 +185,7 @@
 def _read(radio, length):
     try:
         data = radio.pipe.read(length)
-    except Exception, e:
+    except Exception as e:
         LOG.error("Error reading from radio: %s" % e)
         raise errors.RadioError("Unable to read from radio")
 
diff --git a/chirp/drivers/anytone_ht.py b/chirp/drivers/anytone_ht.py
--- a/chirp/drivers/anytone_ht.py
+++ b/chirp/drivers/anytone_ht.py
@@ -233,7 +233,7 @@
 def _echo_write(radio, data):
     try:
         radio.pipe.write(data)
-    except Exception, e:
+    except Exception as e:
         LOG.error("Error writing to radio: %s" % e)
         raise errors.RadioError("Unable to write to radio")
 
@@ -241,7 +241,7 @@
 def _read(radio, length):
     try:
         data = radio.pipe.read(length)
-    except Exception, e:
+    except Exception as e:
         LOG.error("Error reading from radio: %s" % e)
         raise errors.RadioError("Unable to read from radio")
 
@@ -930,7 +930,7 @@
                     else:
                         LOG.debug("Setting %s = %s" % (setting, element.value))
                         setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
 
diff --git a/chirp/drivers/ap510.py b/chirp/drivers/ap510.py
--- a/chirp/drivers/ap510.py
+++ b/chirp/drivers/ap510.py
@@ -44,7 +44,7 @@
 
 def drain(pipe):
     """Chew up any data waiting on @pipe"""
-    for x in xrange(3):
+    for x in range(3):
         buf = pipe.read(4096)
         if not buf:
             return
@@ -53,7 +53,7 @@
 
 def enter_setup(pipe):
     """Put AP510 in configuration mode."""
-    for x in xrange(30):
+    for x in range(30):
         if x % 2:
             pipe.write("@SETUP")
         else:
@@ -84,7 +84,7 @@
         radio.pipe.write("@DISP")
     buf = ""
 
-    for status.cur in xrange(status.cur, status.max):
+    for status.cur in range(status.cur, status.max):
         buf += radio.pipe.read(1024)
         if buf.endswith("\r\n"):
             status.cur = status.max
@@ -242,7 +242,8 @@
 
 class AP510Memory20141215(AP510Memory):
     """Compatible with firmware version 20141215"""
-    ATTR_MAP = dict(AP510Memory.ATTR_MAP.items() + {
+    ATTR_MAP = dict(AP510Memory.ATTR_MAP)
+    ATTR_MAP.update( {
         'tx_volume': '21',  # 1-6
         'rx_volume': '22',  # 1-9
         'tx_power': '23',  # 1: 1 watt,  0: 0.5 watt
@@ -252,7 +253,7 @@
         'path3': '27',  # like "WIDE1 1" else "0"
         'multiple': '28',
         'auto_on': '29',
-    }.items())
+    })
 
     def get_multiple(self):
         return dict(zip(
@@ -380,7 +381,7 @@
             data = download(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
 
         # _mmap isn't a Chirp MemoryMap, but since AP510Memory implements
@@ -398,12 +399,12 @@
             upload(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
 
     def load_mmap(self, filename):
         """Load the radio's memory map from @filename"""
-        mapfile = file(filename, "rb")
+        mapfile = open(filename, "rb")
         data = mapfile.read()
         if data.startswith('\r\n00=%s 20141215' % self._model):
             self._mmap = AP510Memory20141215(data)
diff --git a/chirp/drivers/baofeng_common.py b/chirp/drivers/baofeng_common.py
--- a/chirp/drivers/baofeng_common.py
+++ b/chirp/drivers/baofeng_common.py
@@ -16,6 +16,8 @@
 
 """common functions for Baofeng (or similar) handheld radios"""
 
+from __future__ import print_function
+
 import time
 import struct
 import logging
@@ -164,8 +166,8 @@
         try:
             data = _do_ident(radio, magic)
             return data
-        except errors.RadioError, e:
-            print e
+        except errors.RadioError as e:
+            print(e)
             error = e
             time.sleep(2)
     if error:
@@ -336,7 +338,7 @@
             _upload(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             # If anything unexpected happens, make sure we raise
             # a RadioError and log the problem
             LOG.exception('Unexpected error during upload')
@@ -622,7 +624,7 @@
                     elif element.value.get_mutable():
                         LOG.debug("Setting %s = %s" % (setting, element.value))
                         setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
 
@@ -636,6 +638,6 @@
                     value = int(val.get_value() * 10)
                 LOG.debug("Setting fm_presets = %s" % (value))
                 self._memobj.fm_presets = value
-            except Exception, e:
+            except Exception as e:
                 LOG.debug(element.get_name())
                 raise
diff --git a/chirp/drivers/baofeng_uv3r.py b/chirp/drivers/baofeng_uv3r.py
--- a/chirp/drivers/baofeng_uv3r.py
+++ b/chirp/drivers/baofeng_uv3r.py
@@ -19,7 +19,7 @@
 import os
 import logging
 
-from wouxun_common import do_download, do_upload
+from chirp.drivers.wouxun_common import do_download, do_upload
 from chirp import util, chirp_common, bitwise, errors, directory
 from chirp.settings import RadioSetting, RadioSettingGroup, \
                 RadioSettingValueBoolean, RadioSettingValueList, \
@@ -51,10 +51,9 @@
     for _i in range(0, 10):
         try:
             return _uv3r_prep(radio)
-        except errors.RadioError, e:
+        except errors.RadioError as e:
             time.sleep(1)
-
-    raise e
+            raise e
 
 
 def uv3r_download(radio):
@@ -64,7 +63,7 @@
         return do_download(radio, 0x0000, 0x0E40, 0x0010)
     except errors.RadioError:
         raise
-    except Exception, e:
+    except Exception as e:
         raise errors.RadioError("Failed to communicate with radio: %s" % e)
 
 
@@ -75,7 +74,7 @@
         return do_upload(radio, 0x0000, 0x0E40, 0x0010)
     except errors.RadioError:
         raise
-    except Exception, e:
+    except Exception as e:
         raise errors.RadioError("Failed to communicate with radio: %s" % e)
 
 
@@ -623,7 +622,7 @@
                     else:
                         LOG.debug("Setting %s = %s" % (setting, element.value))
                         setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
 
@@ -639,7 +638,7 @@
                 LOG.debug("Setting fm_presets[%1i] = %s" % (index, value))
                 setting = self._memobj.fm_presets
                 setting[index] = value
-            except Exception, e:
+            except Exception as e:
                 LOG.debug(element.get_name())
                 raise
 
diff --git a/chirp/drivers/bf-t1.py b/chirp/drivers/bf-t1.py
--- a/chirp/drivers/bf-t1.py
+++ b/chirp/drivers/bf-t1.py
@@ -225,7 +225,7 @@
 
     except errors.RadioError:
         raise
-    except Exception, e:
+    except Exception as e:
         raise errors.RadioError("Error sending Magic to radio:\n%s" % e)
 
 
@@ -561,7 +561,7 @@
             _upload(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Error: %s" % e)
 
     def _decode_tone(self, val, inv):
@@ -894,7 +894,7 @@
                     setattr(_settings, name, value)
 
                 LOG.debug("Setting %s: %s" % (name, value))
-            except Exception, e:
+            except Exception as e:
                 LOG.debug(element.get_name())
                 raise
 
diff --git a/chirp/drivers/bj9900.py b/chirp/drivers/bj9900.py
--- a/chirp/drivers/bj9900.py
+++ b/chirp/drivers/bj9900.py
@@ -178,7 +178,7 @@
             self._mmap = self._clone_in()
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
         self.process_mmap()
 
@@ -187,7 +187,7 @@
             self._clone_out()
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
 
     def process_mmap(self):
diff --git a/chirp/drivers/bjuv55.py b/chirp/drivers/bjuv55.py
--- a/chirp/drivers/bjuv55.py
+++ b/chirp/drivers/bjuv55.py
@@ -647,6 +647,6 @@
                 value = int(val.get_value() * 10 - 870)
                 LOG.debug("Setting fm_preset = %s" % (value))
                 self._memobj.fm_preset = value
-            except Exception, e:
+            except Exception as e:
                 LOG.debug(element.get_name())
                 raise
diff --git a/chirp/drivers/fd268.py b/chirp/drivers/fd268.py
--- a/chirp/drivers/fd268.py
+++ b/chirp/drivers/fd268.py
@@ -790,11 +790,11 @@
                         obj = getattr(_mem, sett)
                         setattr(obj, name, element.value)
 
-                    except AttributeError, e:
+                    except AttributeError as e:
                         m = "Setting %s is not in this setting block" % name
                         LOG.debug(m)
 
-            except Exception, e:
+            except Exception as e:
                 LOG.debug(element.get_name())
                 raise
 
diff --git a/chirp/drivers/ft1d.py b/chirp/drivers/ft1d.py
--- a/chirp/drivers/ft1d.py
+++ b/chirp/drivers/ft1d.py
@@ -1890,7 +1890,7 @@
                 except AttributeError as e:
                     LOG.error("Setting %s is not in the memory map: %s" %
                               (element.get_name(), e))
-            except Exception, e:
+            except Exception as e:
                 LOG.debug(element.get_name())
                 raise
 
diff --git a/chirp/drivers/ft2800.py b/chirp/drivers/ft2800.py
--- a/chirp/drivers/ft2800.py
+++ b/chirp/drivers/ft2800.py
@@ -18,7 +18,7 @@
 import logging
 
 from chirp import util, memmap, chirp_common, bitwise, directory, errors
-from yaesu_clone import YaesuCloneModeRadio
+from chirp.drivers.yaesu_clone import YaesuCloneModeRadio
 
 LOG = logging.getLogger(__name__)
 
@@ -201,7 +201,7 @@
             self._mmap = _download(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
         LOG.info("Downloaded in %.2f sec" % (time.time() - start))
         self.process_mmap()
@@ -214,7 +214,7 @@
             _upload(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
         LOG.info("Uploaded in %.2f sec" % (time.time() - start))
 
diff --git a/chirp/drivers/ft2900.py b/chirp/drivers/ft2900.py
--- a/chirp/drivers/ft2900.py
+++ b/chirp/drivers/ft2900.py
@@ -537,7 +537,7 @@
             self._mmap = _download(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
         LOG.info("Downloaded in %.2f sec" % (time.time() - start))
         self.process_mmap()
@@ -549,7 +549,7 @@
             _upload(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
         LOG.info("Uploaded in %.2f sec" % (time.time() - start))
 
@@ -1210,7 +1210,7 @@
                     setattr(_settings, name, value)
 
                 LOG.debug("Setting %s: %s" % (name, value))
-            except Exception, e:
+            except Exception as e:
                 LOG.debug(element.get_name())
                 raise
 
diff --git a/chirp/drivers/ft450d.py b/chirp/drivers/ft450d.py
--- a/chirp/drivers/ft450d.py
+++ b/chirp/drivers/ft450d.py
@@ -304,10 +304,10 @@
         struct mem_struct current;
 
     """
-    _CALLSIGN_CHARSET = [chr(x) for x in range(ord("0"), ord("9") + 1) +
-                        range(ord("A"), ord("Z") + 1) + [ord(" ")]]
+    _CALLSIGN_CHARSET = [chr(x) for x in list(range(ord("0"), ord("9") + 1)) +
+                        list(range(ord("A"), ord("Z") + 1)) + [ord(" ")]]
     _CALLSIGN_CHARSET_REV = dict(zip(_CALLSIGN_CHARSET,
-                                     range(0, len(_CALLSIGN_CHARSET))))
+                                     list(range(0, len(_CALLSIGN_CHARSET)))))
 
     # WARNING Indecis are hard wired in get/set_memory code !!!
     # Channels print in + increasing index order (PMS first)
@@ -499,7 +499,7 @@
             self._mmap = self._clone_in()
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s"
                                     % e)
         self.process_mmap()
@@ -509,7 +509,7 @@
             self._clone_out()
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s"
                                     % e)
 
@@ -1489,6 +1489,6 @@
                     elif element.value.get_mutable():
                         LOG.debug("Setting %s = %s" % (setting, element.value))
                         setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
diff --git a/chirp/drivers/ft50.py b/chirp/drivers/ft50.py
--- a/chirp/drivers/ft50.py
+++ b/chirp/drivers/ft50.py
@@ -586,7 +586,7 @@
 def _clone_out(radio):
     try:
         return __clone_out(radio)
-    except Exception, e:
+    except Exception as e:
         raise errors.RadioError("Failed to communicate with the radio: %s" % e)
 
 
diff --git a/chirp/drivers/ft60.py b/chirp/drivers/ft60.py
--- a/chirp/drivers/ft60.py
+++ b/chirp/drivers/ft60.py
@@ -403,7 +403,7 @@
             self._mmap = _download(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
         self.process_mmap()
         self.check_checksums()
@@ -414,7 +414,7 @@
             _upload(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
 
     def process_mmap(self):
@@ -716,7 +716,7 @@
                     setattr(_settings, name, value)
 
                 LOG.debug("Setting %s: %s" % (name, value))
-            except Exception, e:
+            except Exception as e:
                 LOG.debug(element.get_name())
                 raise
 
diff --git a/chirp/drivers/ft70.py b/chirp/drivers/ft70.py
--- a/chirp/drivers/ft70.py
+++ b/chirp/drivers/ft70.py
@@ -527,8 +527,8 @@
     _DG_ID = ["%d" % x for x in range(0, 100)]
     _GM_RING = ("OFF", "IN RING", "AlWAYS")
     _GM_INTERVAL = ("LONG", "NORMAL", "OFF")
-
-    _MYCALL_CHR_SET = list(string.uppercase) + list(string.digits) + ['-','/' ]
+    #TODO: 2to3 python3 string.uppercase removed; do we need python2 string.uppercase locale dependent functionality? https://stackoverflow.com/questions/4942239/python-string-uppercase-vs-string-ascii-uppercase
+    _MYCALL_CHR_SET = list(string.ascii_uppercase) + list(string.digits) + ['-','/' ] 
 
     @classmethod
     def get_prompts(cls):
@@ -1162,7 +1162,7 @@
                 except AttributeError as e:
                     LOG.error("Setting %s is not in the memory map: %s" %
                               (element.get_name(), e))
-            except Exception, e:
+            except Exception as e:
                 LOG.debug(element.get_name())
                 raise
 
diff --git a/chirp/drivers/ft7100.py b/chirp/drivers/ft7100.py
--- a/chirp/drivers/ft7100.py
+++ b/chirp/drivers/ft7100.py
@@ -568,7 +568,7 @@
             self._mmap = _download(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
         LOG.info("Downloaded in %.2f sec", (time.time() - start))
         self.process_mmap()
@@ -580,7 +580,7 @@
             _upload(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
         LOG.info("Uploaded in %.2f sec", (time.time() - start))
 
@@ -1091,7 +1091,7 @@
                     setattr(_overlay, name, value)
 
                 LOG.debug("Setting %s: %s", name, value)
-            except Exception, e:
+            except Exception as e:
                 LOG.debug(element.get_name())
                 raise
 
diff --git a/chirp/drivers/ft8100.py b/chirp/drivers/ft8100.py
--- a/chirp/drivers/ft8100.py
+++ b/chirp/drivers/ft8100.py
@@ -13,6 +13,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+from __future__ import print_function
+
 import time
 import os
 
@@ -175,7 +177,7 @@
 
         if _mem.duplex == DUPLEX.index("split"):
             tx_freq = int(_mem.offset) * 1000
-            print self.VARIANT, number, tx_freq, mem.freq
+            print(self.VARIANT, number, tx_freq, mem.freq)
             mem.offset = tx_freq - mem.freq
         else:
             mem.offset = int(_mem.offset) * 1000
@@ -189,7 +191,7 @@
         if not self._memobj.enables[byte] & bit and number != 1:
             mem.empty = True
 
-        print 'R', self.VARIANT, number, _mem.baud9600
+        print('R', self.VARIANT, number, _mem.baud9600)
 
         return mem
 
@@ -270,7 +272,7 @@
 def _clone_out(radio):
     try:
         return __clone_out(radio)
-    except Exception, e:
+    except Exception as e:
         raise errors.RadioError("Failed to communicate with the radio: %s" % e)
 
 
@@ -291,7 +293,7 @@
     pos = 0
     for block in radio._block_lengths:
         if os.getenv("CHIRP_DEBUG"):
-            print "\nSending %i-%i" % (pos, pos + block)
+            print("\nSending %i-%i" % (pos, pos + block))
         out = radio.get_mmap()[pos:pos + block]
 
         # need to chew byte-by-byte here or else we lose the ACK...not sure why
@@ -309,6 +311,6 @@
 
         pos += block
 
-    print "Clone completed in %i seconds" % (time.time() - start)
+    print("Clone completed in %i seconds" % (time.time() - start))
 
     return True
diff --git a/chirp/drivers/ft90.py b/chirp/drivers/ft90.py
--- a/chirp/drivers/ft90.py
+++ b/chirp/drivers/ft90.py
@@ -52,7 +52,8 @@
                          chirp_common.PowerLevel("Low", watts=5)]
 
 FT90_DUPLEX = ["", "-", "+", "split"]
-FT90_CWID_CHARS = list(string.digits) + list(string.uppercase) + list(" ")
+#TODO: 2to3 python3 string.uppercase removed; do we need python2 string.uppercase locale dependent functionality? https://stackoverflow.com/questions/4942239/python-string-uppercase-vs-string-ascii-uppercase
+FT90_CWID_CHARS = list(string.digits) + list(string.ascii_uppercase) + list(" ")
 FT90_DTMF_CHARS = list("0123456789ABCD*#")
 FT90_SPECIAL = ["vfo_vhf", "home_vhf", "vfo_uhf", "home_uhf",
                 "pms_1L", "pms_1U", "pms_2L", "pms_2U"]
@@ -332,7 +333,7 @@
             self._mmap = self._clone_in()
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             trace = traceback.format_exc()
             raise errors.RadioError(
                     "Failed to communicate with radio: %s" % trace)
@@ -343,7 +344,7 @@
             self._clone_out()
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             trace = traceback.format_exc()
             raise errors.RadioError(
                     "Failed to communicate with radio: %s" % trace)
@@ -670,6 +671,6 @@
                     newval = self._dtmf2bbcd(newval)
                 LOG.debug("Setting %s(%s) <= %s" % (setting, oldval, newval))
                 setattr(_settings, setting, newval)
-            except Exception, e:
+            except Exception as e:
                 LOG.debug(element.get_name())
                 raise
diff --git a/chirp/drivers/ftm350.py b/chirp/drivers/ftm350.py
--- a/chirp/drivers/ftm350.py
+++ b/chirp/drivers/ftm350.py
@@ -278,7 +278,7 @@
             self._mmap = _clone_in(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to download from radio (%s)" % e)
         self.process_mmap()
 
@@ -287,7 +287,7 @@
             _clone_out(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to upload to radio (%s)" % e)
 
     def process_mmap(self):
diff --git a/chirp/drivers/kguv8d.py b/chirp/drivers/kguv8d.py
--- a/chirp/drivers/kguv8d.py
+++ b/chirp/drivers/kguv8d.py
@@ -376,7 +376,7 @@
             self._mmap = self._download()
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
         self.process_mmap()
 
@@ -393,7 +393,7 @@
             return self._do_download(0, 32768, 64)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             LOG.exception('Unknown error during download process')
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
 
@@ -426,7 +426,7 @@
             self._do_upload(0, 32768, 64)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
         return
 
diff --git a/chirp/drivers/kguv8dplus.py b/chirp/drivers/kguv8dplus.py
--- a/chirp/drivers/kguv8dplus.py
+++ b/chirp/drivers/kguv8dplus.py
@@ -418,7 +418,7 @@
             self._mmap = self._download()
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
         self.process_mmap()
 
@@ -435,7 +435,7 @@
             return self._do_download(0, 32768, 64)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             LOG.exception('Unknown error during download process')
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
 
@@ -467,7 +467,7 @@
             self._do_upload(0, 32768, 64)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
         return
 
@@ -1103,9 +1103,9 @@
                             setattr(obj, setting, int(element.value)/10)
                         else:
                             setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
 
     def _is_freq(self, element):
-        return "rxfreq" in element.get_name() or "txoffset" in element.get_name() or "rx_start" in element.get_name() or "rx_stop" in element.get_name() or "tx_start" in element.get_name() or "tx_stop" in element.get_name()
\ No newline at end of file
+        return "rxfreq" in element.get_name() or "txoffset" in element.get_name() or "rx_start" in element.get_name() or "rx_stop" in element.get_name() or "tx_start" in element.get_name() or "tx_stop" in element.get_name()
diff --git a/chirp/drivers/kguv8e.py b/chirp/drivers/kguv8e.py
--- a/chirp/drivers/kguv8e.py
+++ b/chirp/drivers/kguv8e.py
@@ -337,7 +337,7 @@
 
         try:
             self.pipe.write(_header)
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
 
     def _read_record(self):
@@ -423,7 +423,7 @@
             self._mmap = self._download()
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
         self.process_mmap()
 
@@ -440,7 +440,7 @@
             return self._do_download(0, 32768, 64)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             LOG.exception('Unknown error during download process')
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
 
@@ -472,7 +472,7 @@
             self._do_upload(0, 32768, 64)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
         return
 
@@ -1138,7 +1138,7 @@
                             setattr(obj, setting, int(element.value)/10)
                         else:
                             setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
 
diff --git a/chirp/drivers/kguv9dplus.py b/chirp/drivers/kguv9dplus.py
--- a/chirp/drivers/kguv9dplus.py
+++ b/chirp/drivers/kguv9dplus.py
@@ -877,7 +877,7 @@
             self._write_record(CMD_HANGUP)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             LOG.exception('Unknown error during download process')
             raise errors.RadioError(
                 "Failed to communicate with radio: %s" % e)
@@ -894,7 +894,7 @@
             self._write_record(CMD_HANGUP)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError(
                 "Failed to communicate with radio: %s" % e)
         return
@@ -1887,7 +1887,7 @@
                             setattr(obj, setting, int(element.value)/10)
                         else:
                             setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug("set_settings: Exception with %s" %
                               element.get_name())
                     raise
diff --git a/chirp/drivers/kyd.py b/chirp/drivers/kyd.py
--- a/chirp/drivers/kyd.py
+++ b/chirp/drivers/kyd.py
@@ -500,7 +500,7 @@
 
                     LOG.debug("Setting %s = %s" % (setting, element.value))
                     setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
 
diff --git a/chirp/drivers/kyd_IP620.py b/chirp/drivers/kyd_IP620.py
--- a/chirp/drivers/kyd_IP620.py
+++ b/chirp/drivers/kyd_IP620.py
@@ -20,6 +20,8 @@
 # TODO: Channel name
 # TODO: Tuning step
 
+from __future__ import print_function
+
 import struct
 import time
 import os
@@ -181,7 +183,7 @@
             self.pipe.write("\x06")
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Radio refused to exit programming mode: %s" % e)
 
     def _ip620_enter_programming_mode(self):
@@ -192,7 +194,7 @@
             _ack = self.pipe.read(1)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Error communicating with radio: %s" % e)
         if not _ack:
             raise errors.RadioError("No response from radio")
@@ -203,17 +205,17 @@
             _ident = self.pipe.read(8)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Error communicating with radio: %s" % e)
         if not _ident.startswith("\x06\x4B\x47\x36\x37\x01\x56\xF8"):
-            print util.hexprint(_ident)
+            print(util.hexprint(_ident))
             raise errors.RadioError("Radio returned unknown identification string")
         try:
             self.pipe.write(CMD_ACK)
             _ack = self.pipe.read(1)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Error communicating with radio: %s" % e)
         if _ack != CMD_ACK:
             raise errors.RadioError("Radio refused to enter programming mode")
@@ -316,7 +318,7 @@
             self._mmap = self._do_download()
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
         self.process_mmap()
 
@@ -597,7 +599,7 @@
                 setattr(self._memobj.settings_misc,
                         element.get_name(),
                         element.value)
-            except Exception, e:
+            except Exception as e:
                 LOG.debug(element.get_name())
                 raise
 
@@ -624,6 +626,6 @@
                     setattr(_settings_misc, setting, newval)
                 else:
                     setattr(_settings, setting, newval)
-            except Exception, e:
+            except Exception as e:
                 LOG.debug(element.get_name())
                 raise
diff --git a/chirp/drivers/leixen.py b/chirp/drivers/leixen.py
--- a/chirp/drivers/leixen.py
+++ b/chirp/drivers/leixen.py
@@ -226,7 +226,7 @@
                    ]
 
 MODES = ["NFM", "FM"]
-WTFTONES = map(float, xrange(56, 64))
+WTFTONES = list(map(float, range(56, 64)))
 TONES = WTFTONES + chirp_common.TONES
 DTCS_CODES = [17, 50, 645] + chirp_common.DTCS_CODES
 DTCS_CODES.sort()
@@ -261,7 +261,7 @@
     #            util.hexprint(frame).replace("\n", "\n          ")))
     try:
         radio.pipe.write(frame)
-    except Exception, e:
+    except Exception as e:
         raise errors.RadioError("Failed to communicate with radio: %s" % e)
 
 
@@ -427,7 +427,7 @@
     def sync_in(self):
         try:
             self._mmap = do_download(self)
-        except Exception, e:
+        except Exception as e:
             finish(self)
             raise errors.RadioError("Failed to download from radio: %s" % e)
         self.process_mmap()
@@ -442,7 +442,7 @@
         except errors.RadioError:
             finish(self)
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to upload to radio: %s" % e)
 
     def get_raw_memory(self, number):
@@ -941,7 +941,7 @@
                     else:
                         LOG.debug("Setting %s = %s" % (setting, element.value))
                         setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
 
diff --git a/chirp/drivers/lt725uv.py b/chirp/drivers/lt725uv.py
--- a/chirp/drivers/lt725uv.py
+++ b/chirp/drivers/lt725uv.py
@@ -1393,7 +1393,7 @@
                     elif element.value.get_mutable():
                         LOG.debug("Setting %s = %s" % (setting, element.value))
                         setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
 
diff --git a/chirp/drivers/puxing.py b/chirp/drivers/puxing.py
--- a/chirp/drivers/puxing.py
+++ b/chirp/drivers/puxing.py
@@ -47,7 +47,7 @@
     for _i in range(0, 10):
         try:
             return _puxing_prep(radio)
-        except Exception, e:
+        except Exception as e:
             time.sleep(1)
 
     raise e
@@ -60,7 +60,7 @@
         return do_download(radio, 0x0000, 0x0C60, 0x0008)
     except errors.RadioError:
         raise
-    except Exception, e:
+    except Exception as e:
         raise errors.RadioError("Failed to communicate with radio: %s" % e)
 
 
@@ -71,7 +71,7 @@
         return do_upload(radio, 0x0000, 0x0C40, 0x0008)
     except errors.RadioError:
         raise
-    except Exception, e:
+    except Exception as e:
         raise errors.RadioError("Failed to communicate with radio: %s" % e)
 
 POWER_LEVELS = [chirp_common.PowerLevel("High", watts=5.00),
@@ -372,7 +372,7 @@
         return do_download(radio, 0x0000, 0x0FE0, 0x0010)
     except errors.RadioError:
         raise
-    except Exception, e:
+    except Exception as e:
         raise errors.RadioError("Failed to communicate with radio: %s" % e)
 
 
@@ -383,7 +383,7 @@
         return do_upload(radio, 0x0000, 0x0FE0, 0x0010)
     except errors.RadioError:
         raise
-    except Exception, e:
+    except Exception as e:
         raise errors.RadioError("Failed to communicate with radio: %s" % e)
 
 PUXING_2R_MEM_FORMAT = """
diff --git a/chirp/drivers/puxing_px888k.py b/chirp/drivers/puxing_px888k.py
--- a/chirp/drivers/puxing_px888k.py
+++ b/chirp/drivers/puxing_px888k.py
@@ -527,7 +527,7 @@
 TONE_RESET_TIME = ['Off'] + ['%ds' % x for x in range(1, 256)]
 DTMF_TONE_RESET_TIME = TONE_RESET_TIME[0:16]
 
-DTMF_GROUPS = zip(["Off", "A", "B", "C", "D", "*", "#"], [255]+range(10, 16))
+DTMF_GROUPS = zip(["Off", "A", "B", "C", "D", "*", "#"], [255]+list(range(10, 16)))
 FIVE_TONE_STANDARDS = ['ZVEI1', 'ZVEI2', 'CCIR1', 'CCITT']
 
 # should mimic the defaults in the memedit MemoryEditor somewhat
@@ -543,10 +543,10 @@
 DTMF_ALERT_TRANSPOND = zip(['Off', 'Call alert',
                             'Transpond-alert',
                             'Transpond-ID code'],
-                           [255]+range(1, 4))
+                           [255]+list(range(1, 4)))
 FIVE_TONE_ALERT_TRANSPOND = zip(['Off', 'Alert tone',
                                  'Transpond', 'Transpond-ID code'],
-                                [255]+range(1, 4))
+                                [255]+list(range(1, 4)))
 
 BFM_BANDS = ['87.5-108MHz', '76.0-91.0MHz', '76.0-108.0MHz', '65.0-76.0MHz']
 BFM_STRIDE = ['100kHz', '50kHz']
diff --git a/chirp/drivers/radioddity_r2.py b/chirp/drivers/radioddity_r2.py
--- a/chirp/drivers/radioddity_r2.py
+++ b/chirp/drivers/radioddity_r2.py
@@ -611,7 +611,7 @@
 
                     LOG.debug("Setting %s = %s" % (setting, element.value))
                     setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
 
diff --git a/chirp/drivers/radtel_t18.py b/chirp/drivers/radtel_t18.py
--- a/chirp/drivers/radtel_t18.py
+++ b/chirp/drivers/radtel_t18.py
@@ -478,7 +478,7 @@
                     else:
                         LOG.debug("Setting %s = %s" % (setting, element.value))
                         setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
 
diff --git a/chirp/drivers/retevis_rt1.py b/chirp/drivers/retevis_rt1.py
--- a/chirp/drivers/retevis_rt1.py
+++ b/chirp/drivers/retevis_rt1.py
@@ -726,7 +726,7 @@
                     elif element.value.get_mutable():
                         LOG.debug("Setting %s = %s" % (setting, element.value))
                         setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
 
diff --git a/chirp/drivers/retevis_rt21.py b/chirp/drivers/retevis_rt21.py
--- a/chirp/drivers/retevis_rt21.py
+++ b/chirp/drivers/retevis_rt21.py
@@ -561,7 +561,7 @@
                     elif element.value.get_mutable():
                         LOG.debug("Setting %s = %s" % (setting, element.value))
                         setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
                     
diff --git a/chirp/drivers/retevis_rt22.py b/chirp/drivers/retevis_rt22.py
--- a/chirp/drivers/retevis_rt22.py
+++ b/chirp/drivers/retevis_rt22.py
@@ -605,7 +605,7 @@
 
                     LOG.debug("Setting %s = %s" % (setting, element.value))
                     setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
 
diff --git a/chirp/drivers/retevis_rt23.py b/chirp/drivers/retevis_rt23.py
--- a/chirp/drivers/retevis_rt23.py
+++ b/chirp/drivers/retevis_rt23.py
@@ -846,7 +846,7 @@
                     elif element.value.get_mutable():
                         LOG.debug("Setting %s = %s" % (setting, element.value))
                         setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
 
diff --git a/chirp/drivers/retevis_rt26.py b/chirp/drivers/retevis_rt26.py
--- a/chirp/drivers/retevis_rt26.py
+++ b/chirp/drivers/retevis_rt26.py
@@ -897,7 +897,7 @@
                     elif element.value.get_mutable():
                         LOG.debug("Setting %s = %s" % (setting, element.value))
                         setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
 
diff --git a/chirp/drivers/rfinder.py b/chirp/drivers/rfinder.py
--- a/chirp/drivers/rfinder.py
+++ b/chirp/drivers/rfinder.py
@@ -240,7 +240,7 @@
                 dist = distance(self.__lat, self.__lon, lat, lon)
                 bear = fuzzy_to(self.__lat, self.__lon, lat, lon)
                 mem.comment = "(%imi %s) %s" % (dist, bear, mem.comment)
-            except Exception, e:
+            except Exception as e:
                 LOG.error("Failed to calculate distance: %s" % e)
 
         return mem
@@ -258,7 +258,7 @@
                 mem.number = number
                 number += 1
                 self.__memories.append(mem)
-            except Exception, e:
+            except Exception as e:
                 import traceback
                 LOG.error(traceback.format_exc())
                 LOG.error("Error in received data, cannot continue")
@@ -287,8 +287,9 @@
 
         self._rfp = None
 
-    def set_params(self, (lat, lon), miles, email, password):
+    def set_params(self, lat_lon_tuple, miles, email, password):
         """Sets the parameters to use for the query"""
+        lat, lon = lat_lon_tuple #py3: PEP 3113 – Removal of Tuple Parameter Unpacking https://peps.python.org/pep-3113/
         self._lat = lat
         self._lon = lon
         self._miles = miles
diff --git a/chirp/drivers/rh5r_v2.py b/chirp/drivers/rh5r_v2.py
--- a/chirp/drivers/rh5r_v2.py
+++ b/chirp/drivers/rh5r_v2.py
@@ -15,6 +15,8 @@
 
 """Rugged RH5R V2 radio management module"""
 
+from __future__ import print_function
+
 import struct
 import logging
 
@@ -167,7 +169,7 @@
                 filedata[0x840:0x848] == cls._FILEID)
 
     def process_mmap(self):
-        print MEM_FORMAT
+        print(MEM_FORMAT)
         self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
 
     def get_raw_memory(self, number):
diff --git a/chirp/drivers/tdxone_tdq8a.py b/chirp/drivers/tdxone_tdq8a.py
--- a/chirp/drivers/tdxone_tdq8a.py
+++ b/chirp/drivers/tdxone_tdq8a.py
@@ -14,6 +14,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+from __future__ import print_function
+
 import time
 import struct
 import logging
@@ -301,8 +303,8 @@
         try:
             data = _do_ident(radio, magic)
             return data
-        except errors.RadioError, e:
-            print e
+        except errors.RadioError as e:
+            print(e)
             error = e
             time.sleep(2)
     if error:
@@ -426,7 +428,7 @@
 
     if len(data) == 0x2008:
         rid = data[0x2000:0x2008]
-        print rid
+        print(rid)
         return rid.startswith(cls.MODEL)
     else:
         return False
@@ -1117,7 +1119,7 @@
                     elif element.value.get_mutable():
                         LOG.debug("Setting %s = %s" % (setting, element.value))
                         setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
 
@@ -1131,7 +1133,7 @@
                     value = int(val.get_value() * 10)
                 LOG.debug("Setting fm_presets = %s" % (value))
                 self._memobj.fm_presets = value
-            except Exception, e:
+            except Exception as e:
                 LOG.debug(element.get_name())
                 raise
 
diff --git a/chirp/drivers/th7800.py b/chirp/drivers/th7800.py
--- a/chirp/drivers/th7800.py
+++ b/chirp/drivers/th7800.py
@@ -536,7 +536,7 @@
 
                 LOG.debug("Setting %s(%s) <= %s" % (setting, oldval, newval))
                 setattr(_settings, setting, newval)
-            except Exception, e:
+            except Exception as e:
                 LOG.debug(element.get_name())
                 raise
 
@@ -726,7 +726,7 @@
     def sync_in(self):
         try:
             self._mmap = _download(self)
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError(
                     "Failed to communicate with the radio: %s" % e)
         self.process_mmap()
@@ -734,6 +734,6 @@
     def sync_out(self):
         try:
             _upload(self)
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError(
                     "Failed to communicate with the radio: %s" % e)
diff --git a/chirp/drivers/th9000.py b/chirp/drivers/th9000.py
--- a/chirp/drivers/th9000.py
+++ b/chirp/drivers/th9000.py
@@ -352,7 +352,7 @@
     try:
         radio.pipe.write(data)
         radio.pipe.read(len(data))
-    except Exception, e:
+    except Exception as e:
         LOG.error("Error writing to radio: %s" % e)
         raise errors.RadioError("Unable to write to radio")
 
@@ -366,7 +366,7 @@
 def _read(radio, length):
     try:
         data = radio.pipe.read(length)
-    except Exception, e:
+    except Exception as e:
         LOG.error( "Error reading from radio: %s" % e)
         raise errors.RadioError("Unable to read from radio")
 
@@ -793,7 +793,7 @@
                     else:
                         LOG.debug( "Setting %s = %s" % (setting, element.value))
                         setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug( element.get_name())
                     raise
 
diff --git a/chirp/drivers/th9800.py b/chirp/drivers/th9800.py
--- a/chirp/drivers/th9800.py
+++ b/chirp/drivers/th9800.py
@@ -598,7 +598,7 @@
 
                 LOG.debug("Setting %s(%s) <= %s" % (setting, oldval, newval))
                 setattr(_settings, setting, newval)
-            except Exception, e:
+            except Exception as e:
                 LOG.debug(element.get_name())
                 raise
 
@@ -785,7 +785,7 @@
     def sync_in(self):
         try:
             self._mmap = _download(self)
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError(
                     "Failed to communicate with the radio: %s" % e)
         self.process_mmap()
@@ -793,6 +793,6 @@
     def sync_out(self):
         try:
             _upload(self)
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError(
                     "Failed to communicate with the radio: %s" % e)
diff --git a/chirp/drivers/th_uv3r25.py b/chirp/drivers/th_uv3r25.py
--- a/chirp/drivers/th_uv3r25.py
+++ b/chirp/drivers/th_uv3r25.py
@@ -22,7 +22,7 @@
     RadioSettingValueInteger, RadioSettingValueList, \
     RadioSettingValueBoolean, RadioSettingValueString
 
-from th_uv3r import TYTUV3RRadio, tyt_uv3r_prep, THUV3R_CHARSET
+from chirp.drivers.th_uv3r import TYTUV3RRadio, tyt_uv3r_prep, THUV3R_CHARSET
 
 
 def tyt_uv3r_download(radio):
diff --git a/chirp/drivers/th_uv8000.py b/chirp/drivers/th_uv8000.py
--- a/chirp/drivers/th_uv8000.py
+++ b/chirp/drivers/th_uv8000.py
@@ -1486,6 +1486,6 @@
                     elif element.value.get_mutable():
                         LOG.debug("Setting %s = %s" % (setting, element.value))
                         setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
diff --git a/chirp/drivers/thd72.py b/chirp/drivers/thd72.py
--- a/chirp/drivers/thd72.py
+++ b/chirp/drivers/thd72.py
@@ -14,6 +14,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+from __future__ import print_function
+
 from chirp import chirp_common, errors, util, directory
 from chirp import bitwise, memmap
 from chirp.settings import RadioSettingGroup, RadioSetting, RadioSettings
@@ -581,7 +583,7 @@
                 except AttributeError as e:
                     LOG.error("Setting %s is not in the memory map: %s" %
                               (element.get_name(), e))
-            except Exception, e:
+            except Exception as e:
                 LOG.debug(element.get_name())
                 raise
 
@@ -738,9 +740,9 @@
         return r
 
     def usage():
-        print "Usage: %s <-i input.img>|<-o output.img> -p port " \
+        print("Usage: %s <-i input.img>|<-o output.img> -p port " \
             "[[-f first-addr] [-l last-addr] | [-b list,of,blocks]]" % \
-            sys.argv[0]
+            sys.argv[0])
         sys.exit(1)
 
     opts, args = getopt.getopt(sys.argv[1:], "i:o:p:f:l:b:")
@@ -793,4 +795,4 @@
     else:
         r._mmap = file(fname, "rb").read(r._memsize)
         r.upload(blocks)
-    print "\nDone"
+    print("\nDone")
diff --git a/chirp/drivers/thuv1f.py b/chirp/drivers/thuv1f.py
--- a/chirp/drivers/thuv1f.py
+++ b/chirp/drivers/thuv1f.py
@@ -214,7 +214,7 @@
             self._mmap = uvf1_download(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
         self.process_mmap()
 
@@ -223,7 +223,7 @@
             uvf1_upload(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
 
     @classmethod
diff --git a/chirp/drivers/tk270.py b/chirp/drivers/tk270.py
--- a/chirp/drivers/tk270.py
+++ b/chirp/drivers/tk270.py
@@ -13,6 +13,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+from __future__ import division
+
 import time
 import struct
 import logging
@@ -96,7 +98,7 @@
 
 MEM_SIZE = 0x400
 BLOCK_SIZE = 8
-MEM_BLOCKS = range(0, (MEM_SIZE / BLOCK_SIZE))
+MEM_BLOCKS = range(0, (MEM_SIZE // BLOCK_SIZE)) #TODO: py3 __floordiv__ or __truediv__ ???
 ACK_CMD = "\x06"
 TIMEOUT = 0.05  # from 0.03 up it' s safe, we set in 0.05 for a margin
 
@@ -269,7 +271,7 @@
      # UI progress
     status = chirp_common.Status()
     status.cur = 0
-    status.max = MEM_SIZE / BLOCK_SIZE
+    status.max = MEM_SIZE / BLOCK_SIZE #TODO: py3 __floordiv__ or __truediv__ ???
     status.msg = "Cloning to radio..."
     radio.status_fn(status)
     count = 0
diff --git a/chirp/drivers/tk760.py b/chirp/drivers/tk760.py
--- a/chirp/drivers/tk760.py
+++ b/chirp/drivers/tk760.py
@@ -13,6 +13,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+from __future__ import division
+
 import time
 import struct
 import logging
@@ -97,7 +99,7 @@
 
 MEM_SIZE = 0x400
 BLOCK_SIZE = 8
-MEM_BLOCKS = range(0, (MEM_SIZE / BLOCK_SIZE))
+MEM_BLOCKS = range(0, (MEM_SIZE // BLOCK_SIZE))  #TODO: py3 __floordiv__ or __truediv__ ???
 ACK_CMD = "\x06"
 # from 0.03 up it' s safe
 # I have to turn it up, some users reported problems with this, was 0.05
@@ -256,7 +258,7 @@
      # UI progress
     status = chirp_common.Status()
     status.cur = 0
-    status.max = MEM_SIZE / BLOCK_SIZE
+    status.max = MEM_SIZE / BLOCK_SIZE #TODO: py3 __floordiv__ or __truediv__ ???
     status.msg = "Cloning from radio..."
     radio.status_fn(status)
 
@@ -283,7 +285,7 @@
      # UI progress
     status = chirp_common.Status()
     status.cur = 0
-    status.max = MEM_SIZE / BLOCK_SIZE
+    status.max = MEM_SIZE / BLOCK_SIZE #TODO: py3 __floordiv__ or __truediv__ ???
     status.msg = "Cloning to radio..."
     radio.status_fn(status)
     count = 0
@@ -514,7 +516,7 @@
         """Get the channel scan status from the 4 bytes array on the eeprom
         then from the bits on the byte, return '' or 'S' as needed"""
         result = "S"
-        byte = int(chan/8)
+        byte = int(chan/8) #TODO: py3 __floordiv__ 
         bit = chan % 8
         res = self._memobj.settings.scan[byte] & (pow(2, bit))
         if res > 0:
@@ -524,7 +526,7 @@
 
     def set_scan(self, chan, value):
         """Set the channel scan status from UI to the mem_map"""
-        byte = int(chan/8)
+        byte = int(chan/8) #TODO: py3 __floordiv__
         bit = chan % 8
 
         # get the actual value to see if I need to change anything
@@ -538,14 +540,14 @@
     def get_active(self, chan):
         """Get the channel active status from the 4 bytes array on the eeprom
         then from the bits on the byte, return True/False"""
-        byte = int(chan/8)
+        byte = int(chan/8) #TODO: py3 __floordiv__
         bit = chan % 8
         res = self._memobj.settings.active[byte] & (pow(2, bit))
         return bool(res)
 
     def set_active(self, chan, value=True):
         """Set the channel active status from UI to the mem_map"""
-        byte = int(chan/8)
+        byte = int(chan/8) #TODO: py3 __floordiv__
         bit = chan % 8
 
         # get the actual value to see if I need to change anything
@@ -637,18 +639,18 @@
             return
 
         # freq rx
-        _mem.rxfreq = mem.freq / 10
+        _mem.rxfreq = mem.freq / 10  #TODO: py3 __floordiv__ or __truediv__ ???
 
         # freq tx
         if mem.duplex == "+":
-            _mem.txfreq = (mem.freq + mem.offset) / 10
+            _mem.txfreq = (mem.freq + mem.offset) / 10 #TODO: py3 __floordiv__ or __truediv__ ???
         elif mem.duplex == "-":
-            _mem.txfreq = (mem.freq - mem.offset) / 10
+            _mem.txfreq = (mem.freq - mem.offset) / 10 #TODO: py3 __floordiv__ or __truediv__ ???
         elif mem.duplex == "off":
             for byte in _mem.txfreq:
                 byte.set_raw("\xFF")
         else:
-            _mem.txfreq = mem.freq / 10
+            _mem.txfreq = mem.freq / 10 #TODO: py3 __floordiv__ or __truediv__ ???
 
         # tone data
         ((txmode, txtone, txpol), (rxmode, rxtone, rxpol)) = \
diff --git a/chirp/drivers/tk760g.py b/chirp/drivers/tk760g.py
--- a/chirp/drivers/tk760g.py
+++ b/chirp/drivers/tk760g.py
@@ -13,6 +13,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+from __future__ import division
+
 import logging
 import struct
 import time
@@ -263,13 +265,13 @@
 
 MEM_SIZE = 0x8000  # 32,768 bytes
 BLOCK_SIZE = 256
-BLOCKS = MEM_SIZE / BLOCK_SIZE
-MEM_BLOCKS = range(0, BLOCKS)
+BLOCKS = MEM_SIZE // BLOCK_SIZE #TODO: py3 __floordiv__ or __truediv__ ???
+MEM_BLOCKS = list(range(0, BLOCKS))
 
 # define and empty block of data, as it will be used a lot in this code
 EMPTY_BLOCK = "\xFF" * 256
 
-RO_BLOCKS = range(0x10, 0x1F) + range(0x59, 0x5f)
+RO_BLOCKS = list(range(0x10, 0x1F)) + list(range(0x59, 0x5f))
 ACK_CMD = "\x06"
 
 POWER_LEVELS = [chirp_common.PowerLevel("Low", watts=1),
@@ -529,7 +531,7 @@
 
     # reset UI data
     status.cur = 0
-    status.max = MEM_SIZE / 256
+    status.max = MEM_SIZE // 256 #TODO: py3 __floordiv__ or __truediv__ ???
     status.msg = "Cloning from radio..."
     radio.status_fn(status)
 
@@ -580,7 +582,7 @@
 
     # update UI
     status.cur = 0
-    status.max = MEM_SIZE / 256
+    status.max = MEM_SIZE // 256 #TODO: py3 __floordiv__ or __truediv__ ???
     status.msg = "Cloning to radio..."
     radio.status_fn(status)
 
@@ -843,7 +845,7 @@
         bdata += (256 - (len(bdata)) % 256) * "\xFF"
 
         # fill to match the whole area
-        bdata += (16 - len(bdata) / 256) * EMPTY_BLOCK
+        bdata += (16 - len(bdata) // 256) * EMPTY_BLOCK #TODO: py3 __floordiv__ or __truediv__ ???
 
         # updating the data in the memmap [x1000]
         self._fill(0x1000, bdata)
@@ -907,7 +909,7 @@
             do_upload(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
 
     def process_mmap(self):
@@ -937,7 +939,7 @@
             pol = (val & 0x8000) and "R" or "N"
             return 'DTCS', code, pol
         else:
-            a = val / 10.0
+            a = val / 10.0 #TODO: py3 __floordiv__ or __truediv__ ???
             return 'Tone', a, None
 
     def _encode_tone(self, memval, mode, value, pol):
@@ -958,7 +960,7 @@
         """Get the channel scan status from the 16 bytes array on the eeprom
         then from the bits on the byte, return '' or 'S' as needed"""
         result = "S"
-        byte = int(chan/8)
+        byte = int(chan//8) #TODO: py3 __floordiv__ or __truediv__ ???
         bit = chan % 8
         res = self._memobj.settings.add[byte] & (pow(2, bit))
         if res > 0:
@@ -968,7 +970,7 @@
 
     def _set_scan(self, chan, value):
         """Set the channel scan status from UI to the mem_map"""
-        byte = int(chan/8)
+        byte = int(chan//8) #TODO: py3 __floordiv__ or __truediv__ ???
         bit = chan % 8
 
         # get the actual value to see if I need to change anything
@@ -1086,7 +1088,7 @@
             return
 
         # frequency
-        _mem.rxfreq = mem.freq / 10
+        _mem.rxfreq = mem.freq / 10 #TODO: py3 __floordiv__ or __truediv__ ???
 
         # this are a mistery yet, but so falr there is no impact
         # whit this default values for new channels
@@ -1096,14 +1098,14 @@
 
         # duplex
         if mem.duplex == "+":
-            _mem.txfreq = (mem.freq + mem.offset) / 10
+            _mem.txfreq = (mem.freq + mem.offset) / 10 #TODO: py3 __floordiv__ or __truediv__ ???
         elif mem.duplex == "-":
-            _mem.txfreq = (mem.freq - mem.offset) / 10
+            _mem.txfreq = (mem.freq - mem.offset) / 10 #TODO: py3 __floordiv__ or __truediv__ ???
         elif mem.duplex == "off":
             for byte in _mem.txfreq:
                 byte.set_raw("\xFF")
         else:
-            _mem.txfreq = mem.freq / 10
+            _mem.txfreq = mem.freq / 10 #TODO: py3 __floordiv__ or __truediv__ ???
 
         # tone data
         ((txmode, txtone, txpol), (rxmode, rxtone, rxpol)) = \
diff --git a/chirp/drivers/ts2000.py b/chirp/drivers/ts2000.py
--- a/chirp/drivers/ts2000.py
+++ b/chirp/drivers/ts2000.py
@@ -13,6 +13,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+from __future__ import print_function
+
 import re
 from chirp import chirp_common, directory, util, errors
 from chirp.drivers import kenwood_live
@@ -217,7 +219,7 @@
             duplex = 0
             offset = 0
         else:
-            print "Bug: unsupported duplex `%s'" % mem.duplex
+            print("Bug: unsupported duplex `%s'" % mem.duplex)
         if mem.mode in ["AM", "FM"]:
             step = TS2000_FM_STEPS.index(mem.tuning_step)
         else:
@@ -259,7 +261,7 @@
         elif mem.duplex == "split":
             duplex = 0
         else:
-            print "Bug: unsupported duplex `%s'" % mem.duplex
+            print("Bug: unsupported duplex `%s'" % mem.duplex)
         if mem.mode in ["AM", "FM"]:
             step = TS2000_FM_STEPS.index(mem.tuning_step)
         else:
diff --git a/chirp/drivers/ts480.py b/chirp/drivers/ts480.py
--- a/chirp/drivers/ts480.py
+++ b/chirp/drivers/ts480.py
@@ -1138,7 +1138,7 @@
                     elif element.value.get_mutable():
                         LOG.debug("Setting %s = %s" % (setting, element.value))
                         setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
         return
diff --git a/chirp/drivers/ts590.py b/chirp/drivers/ts590.py
--- a/chirp/drivers/ts590.py
+++ b/chirp/drivers/ts590.py
@@ -1644,7 +1644,7 @@
                     elif element.value.get_mutable():
                         LOG.debug("Setting %s = %s" % (setting, element.value))
                         setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
 
diff --git a/chirp/drivers/ts850.py b/chirp/drivers/ts850.py
--- a/chirp/drivers/ts850.py
+++ b/chirp/drivers/ts850.py
@@ -37,7 +37,7 @@
     "CW-R":  "7",
     "FSK-R": "9",
 }
-TS850_MODES_REV = {val: mode for mode, val in TS850_MODES.iteritems()}
+TS850_MODES_REV = {val: mode for mode, val in TS850_MODES.items()}
 
 TS850_TONES = list(chirp_common.OLD_TONES)
 TS850_TONES.remove(69.3)
diff --git a/chirp/drivers/uv5r.py b/chirp/drivers/uv5r.py
--- a/chirp/drivers/uv5r.py
+++ b/chirp/drivers/uv5r.py
@@ -587,7 +587,7 @@
         data += _read_block(radio, i, 0x40, False)
 
     if append_model:
-        data += radio.MODEL.ljust(8)
+        data += radio.MODEL.ljust(8).encode('utf-8')
 
     LOG.debug("done.")
     return memmap.MemoryMapBytes(data)
diff --git a/chirp/drivers/vgc.py b/chirp/drivers/vgc.py
--- a/chirp/drivers/vgc.py
+++ b/chirp/drivers/vgc.py
@@ -1410,7 +1410,7 @@
                     elif element.value.get_mutable():
                         LOG.debug("Setting %s = %s" % (setting, element.value))
                         setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
 
diff --git a/chirp/drivers/vx6.py b/chirp/drivers/vx6.py
--- a/chirp/drivers/vx6.py
+++ b/chirp/drivers/vx6.py
@@ -871,5 +871,5 @@
                 elif setting == "password":
                     newval = self._encode_chars(newval, 4)
                 setattr(_settings, setting, newval)
-            except Exception, e:
+            except Exception as e:
                 raise
diff --git a/chirp/drivers/vxa700.py b/chirp/drivers/vxa700.py
--- a/chirp/drivers/vxa700.py
+++ b/chirp/drivers/vxa700.py
@@ -177,7 +177,7 @@
             self._mmap = _download(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate " +
                                     "with the radio: %s" % e)
         self.process_mmap()
@@ -192,7 +192,7 @@
             _upload(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate " +
                                     "with the radio: %s" % e)
 
diff --git a/chirp/drivers/wouxun.py b/chirp/drivers/wouxun.py
--- a/chirp/drivers/wouxun.py
+++ b/chirp/drivers/wouxun.py
@@ -23,7 +23,7 @@
                 RadioSettingValueBoolean, RadioSettingValueList, \
                 RadioSettingValueInteger, RadioSettingValueString, \
                 RadioSettingValueFloat, RadioSettings
-from wouxun_common import wipe_memory, do_download, do_upload
+from chirp.drivers.wouxun_common import wipe_memory, do_download, do_upload
 from textwrap import dedent
 
 LOG = logging.getLogger(__name__)
@@ -274,7 +274,7 @@
             return do_download(self, 0x0000, 0x2000, 0x0040)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
 
     def _upload(self):
@@ -285,7 +285,7 @@
             return do_upload(self, 0x0000, 0x2000, 0x0010)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
 
     def sync_in(self):
@@ -658,7 +658,7 @@
                     else:
                         LOG.debug("Setting %s = %s" % (setting, element.value))
                         setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
 
@@ -680,7 +680,7 @@
                 else:
                     setting = self._memobj.fm_presets_1
                 setting[index] = value
-            except Exception, e:
+            except Exception as e:
                 LOG.debug(element.get_name())
                 raise
 
@@ -690,7 +690,7 @@
                 setattr(self._memobj.freq_ranges,
                         element.get_name(),
                         encode_freq(int(element.value)))
-            except Exception, e:
+            except Exception as e:
                 LOG.debug(element.get_name())
                 raise
 
@@ -1397,7 +1397,7 @@
                     else:
                         LOG.debug("Setting %s = %s" % (setting, element.value))
                         setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
 
@@ -1419,7 +1419,7 @@
                 else:
                     setting = self._memobj.fm_presets_1
                 setting[index] = value
-            except Exception, e:
+            except Exception as e:
                 LOG.debug(element.get_name())
                 raise
 
diff --git a/chirp/ui/mainapp.py b/chirp/ui/mainapp.py
--- a/chirp/ui/mainapp.py
+++ b/chirp/ui/mainapp.py
@@ -14,6 +14,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+from __future__ import print_function
+
 from datetime import datetime
 import os
 import tempfile
@@ -1137,7 +1139,7 @@
 
         query = "http://chirp.danplanet.com/query/rb/1.0/app_direct" \
                 "?loc=%s&band=%s&dist=%s" % (loc, band, dist)
-        print query
+        print(query)
 
         # Do this in case the import process is going to take a while
         # to make sure we process events leading up to this
diff --git a/chirp/ui/memdetail.py b/chirp/ui/memdetail.py
--- a/chirp/ui/memdetail.py
+++ b/chirp/ui/memdetail.py
@@ -71,7 +71,7 @@
                 extra_name = self._name.split("_", 1)[1]
                 LOG.debug('Setting extra %s=%r' % (extra_name, newval))
                 self._memory.extra[extra_name].value = newval
-            except settings.InternalError, e:
+            except settings.InternalError as e:
                 self._errfn(self._name, str(e))
                 return str(e)
         else:
