diff --git a/trac/db/api.py b/trac/db/api.py
--- a/trac/db/api.py
+++ b/trac/db/api.py
@@ -36,7 +36,12 @@
 
     def get_supported_schemes():
         """Return the connection URL schemes supported by the connector, and
-        their relative priorities as an iterable of `(scheme, priority)` tuples.
+        their relative priorities as an iterable of `(scheme, priority)`
+        tuples.
+        
+        If `priority` is a negative number, this is indicative of an
+        error  condition with the connector. An error message should be 
+        attached to the `error` attribute of the connector.
         """
 
     def get_connection(path, log=None, **kwargs):
@@ -116,18 +121,17 @@
 
     def _get_connector(self): ### FIXME: Make it public?
         scheme, args = _parse_db_str(self.connection_uri)
-        candidates = {}
-        for connector in self.connectors:
-            for scheme_, priority in connector.get_supported_schemes():
-                if scheme_ != scheme:
-                    continue
-                highest = candidates.get(scheme_, (None, 0))[1]
-                if priority > highest:
-                    candidates[scheme] = (connector, priority)
-
-        connector = candidates.get(scheme, [None])[0]
-        if not connector:
+        candidates = [
+            (priority, connector)
+            for connector in self.connectors
+            for scheme_, priority in connector.get_supported_schemes()
+            if scheme_ == scheme
+        ]
+        if not candidates:
             raise TracError('Unsupported database type "%s"' % scheme)
+        priority, connector = max(candidates)
+        if priority < 0:
+            raise TracError(connector.error)
 
         if scheme == 'sqlite':
             # Special case for SQLite to support a path relative to the
diff --git a/trac/db/mysql_backend.py b/trac/db/mysql_backend.py
--- a/trac/db/mysql_backend.py
+++ b/trac/db/mysql_backend.py
@@ -23,6 +23,7 @@
 from trac.util import get_pkginfo
 from trac.util.compat import close_fds
 from trac.util.text import to_unicode
+from trac.util.translation import _
 
 _like_escape_re = re.compile(r'([/_%])')
 
@@ -64,13 +65,12 @@
 
     def __init__(self):
         self._version = None
+        self.error = None
 
     def get_supported_schemes(self):
-        global has_mysqldb
-        if has_mysqldb:
-            return [('mysql', 1)]
-        else:
-            return []
+        if not has_mysqldb:
+            self.error = _("Cannot load Python bindings for MySQL")
+        yield ('mysql', self.error and -1 or 1)
 
     def get_connection(self, path, log=None, user=None, password=None,
                        host=None, port=None, params={}):
diff --git a/trac/db/postgres_backend.py b/trac/db/postgres_backend.py
--- a/trac/db/postgres_backend.py
+++ b/trac/db/postgres_backend.py
@@ -23,10 +23,25 @@
 from trac.util import get_pkginfo
 from trac.util.compat import close_fds
 from trac.util.text import to_unicode
+from trac.util.translation import _
 
-psycopg = None
-PgSQL = None
+has_psycopg = False
+has_pgsql = False
 PGSchemaError = None
+try:
+    import psycopg2 as psycopg
+    import psycopg2.extensions
+    from psycopg2 import ProgrammingError as PGSchemaError
+    psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
+    has_psycopg = True
+except ImportError:
+    try:
+        from pyPgSQL import PgSQL
+        from pyPgSQL.libpq import OperationalError as PGSchemaError
+        has_pgsql = True
+    except ImportError:
+        pass
+
 
 _like_escape_re = re.compile(r'([/_%])')
 
@@ -41,22 +56,23 @@
 
     def __init__(self):
         self._version = None
+        self.error = None
 
     def get_supported_schemes(self):
-        return [('postgres', 1)]
+        if not (has_psycopg or has_pgsql):
+            self.error = _("Cannot load Python bindings for PostgreSQL")
+        yield ('postgres', self.error and -1 or 1)
 
     def get_connection(self, path, log=None, user=None, password=None,
                        host=None, port=None, params={}):
-        global psycopg
-        global PgSQL
         cnx = PostgreSQLConnection(path, log, user, password, host, port,
                                    params)
         if not self._version:
-            if psycopg:
+            if has_psycopg:
                 self._version = get_pkginfo(psycopg).get('version',
                                                          psycopg.__version__)
                 name = 'psycopg2'
-            elif PgSQL:
+            elif has_pgsql:
                 import pyPgSQL
                 self._version = get_pkginfo(pyPgSQL).get('version',
                                                          pyPgSQL.__version__)
@@ -152,23 +168,9 @@
                  port=None, params={}):
         if path.startswith('/'):
             path = path[1:]
-        # We support both psycopg and PgSQL but prefer psycopg
-        global psycopg
-        global PgSQL
-        global PGSchemaError
-        
-        if not psycopg and not PgSQL:
-            try:
-                import psycopg2 as psycopg
-                import psycopg2.extensions
-                from psycopg2 import ProgrammingError as PGSchemaError
-                psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
-            except ImportError:
-                from pyPgSQL import PgSQL
-                from pyPgSQL.libpq import OperationalError as PGSchemaError
         if 'host' in params:
             host = params['host']
-        if psycopg:
+        if has_psycopg:
             dsn = []
             if path:
                 dsn.append('dbname=' + path)
@@ -182,7 +184,7 @@
                 dsn.append('port=' + str(port))
             cnx = psycopg.connect(' '.join(dsn))
             cnx.set_client_encoding('UNICODE')
-        else:
+        elif has_pgsql:
             # Don't use chatty, inefficient server-side cursors.
             # http://pypgsql.sourceforge.net/pypgsql-faq.html#id2787367
             PgSQL.fetchReturnsList = 1
diff --git a/trac/db/sqlite_backend.py b/trac/db/sqlite_backend.py
--- a/trac/db/sqlite_backend.py
+++ b/trac/db/sqlite_backend.py
@@ -22,6 +22,7 @@
 from trac.db.api import IDatabaseConnector
 from trac.db.util import ConnectionWrapper
 from trac.util import get_pkginfo, getuser
+from trac.util.translation import _
 
 _like_escape_re = re.compile(r'([/_%])')
 
@@ -112,13 +113,21 @@
 
     def __init__(self):
         self._version = None
+        self.error = None
 
     def get_supported_schemes(self):
-        return [('sqlite', 1)]
+        if not have_pysqlite:
+            self.error = _("Cannot load Python bindings for SQLite")
+        elif sqlite.sqlite_version_info >= (3, 3, 3):
+            if sqlite.version_info < (1, 0, 7):
+                self.error = _("Need at least PySqlite 1.0.7 or higher")
+            elif sqlite.version_info[0] == 2 and \
+                    sqlite.version_info < (2, 0, 7):
+                self.error = _("Need at least PySqlite 2.0.7 or higher")
+        yield ('sqlite', self.error and -1 or 1)
 
     def get_connection(self, path, log=None, params={}):
         if not self._version:
-            global sqlite_version_string, have_pysqlite
             self._version = get_pkginfo(sqlite).get(
                 'version', '%d.%d.%s' % sqlite.version_info)
             self.env.systeminfo.extend([('SQLite', sqlite_version_string),

