It looks like a number of people have done something similar so though I would mention my attempt - pgwrap [1][2]. This is also a thin wrapper over psycopg2. This provides the following -<p><pre><code>    * Simplified handling of connections&#x2F;cursor
        * Connection pool (provided by psycopg2.pool)
        * Cursor context handler 
    * Python API to wrap basic SQL functionality 
        * Simple select,update,delete,join methods extending the cursor 
          context handler (also available as stand-alone methods which
          create an implicit cursor for simple queries)
    * Query results as dict (using psycopg2.extras.DictCursor or any other PG Cursor factory)
    * Callable prepared statements
    * Logging support
</code></pre>
Essentially you can do stuff like:<p><pre><code>  &gt;&gt;&gt; import pgwrap
  &gt;&gt;&gt; db = pgwrap.connection(url=&#x27;postgres:&#x2F;&#x2F;localhost&#x27;)
  &gt;&gt;&gt; with db.cursor() as c:
  ...     c.query(&#x27;select version()&#x27;)
  [[&#x27;PostgreSQL...&#x27;]]
  &gt;&gt;&gt; v = db.query_one(&#x27;select version()&#x27;)
  &gt;&gt;&gt; v
  [&#x27;PostgreSQL...&#x27;]
  &gt;&gt;&gt; v.items()
  [(&#x27;version&#x27;, &#x27;PostgreSQL...&#x27;)]
  &gt;&gt;&gt; v[&#x27;version&#x27;]
  &#x27;PostgreSQL...&#x27;

  &gt;&gt;&gt; db.create_table(&#x27;t1&#x27;,&#x27;id serial,name text,count int&#x27;)
  &gt;&gt;&gt; db.create_table(&#x27;t2&#x27;,&#x27;id serial,t1_id int,value text&#x27;)
  &gt;&gt;&gt; db.log = sys.stdout
  &gt;&gt;&gt; db.insert(&#x27;t1&#x27;,{&#x27;name&#x27;:&#x27;abc&#x27;,&#x27;count&#x27;:0},returning=&#x27;id,name&#x27;)
  INSERT INTO t1 (name) VALUES (&#x27;abc&#x27;) RETURNING id,name
  [1, &#x27;abc&#x27;]
  &gt;&gt;&gt; db.insert(&#x27;t2&#x27;,{&#x27;t1_id&#x27;:1,&#x27;value&#x27;:&#x27;t2&#x27;})
  INSERT INTO t2 (t1_id,value) VALUES (1,&#x27;t2&#x27;)
  1
  &gt;&gt;&gt; db.select(&#x27;t1&#x27;)
  SELECT * FROM t1
  [[1, &#x27;abc&#x27;, 0]]
  &gt;&gt;&gt; db.select_one(&#x27;t1&#x27;,where={&#x27;name&#x27;:&#x27;abc&#x27;},columns=(&#x27;name&#x27;,&#x27;count&#x27;))
  SELECT name, count FROM t1 WHERE name = &#x27;abc&#x27;
  [&#x27;abc&#x27;, 0]
  &gt;&gt;&gt; db.join((&#x27;t1&#x27;,&#x27;t2&#x27;),columns=(&#x27;t1.id&#x27;,&#x27;t2.value&#x27;))
  SELECT t1.id, t2.value FROM t1 JOIN t2 ON t1.id = t2.t1_id
  [[1, &#x27;t2&#x27;]]
  &gt;&gt;&gt; db.insert(&#x27;t1&#x27;,{&#x27;name&#x27;:&#x27;abc&#x27;},returning=&#x27;id&#x27;)
  INSERT INTO t1 (name) VALUES (&#x27;abc&#x27;) RETURNING id
  [2]
  &gt;&gt;&gt; db.update(&#x27;t1&#x27;,{&#x27;name&#x27;:&#x27;xyz&#x27;},where={&#x27;name&#x27;:&#x27;abc&#x27;})
  UPDATE t1 SET name = &#x27;xyz&#x27; WHERE name = &#x27;abc&#x27;
  2
  &gt;&gt;&gt; db.update(&#x27;t1&#x27;,{&#x27;count__func&#x27;:&#x27;count + 1&#x27;},where=   {&#x27;count__lt&#x27;:10},returning=&quot;id,count&quot;)
  UPDATE t1 SET count = count + 1 WHERE count &lt; 10 RETURNING id,count
  [[1, 1]]
</code></pre>
Also it allows you to create callable prepared statements (which I find really useful in structuring apps):<p><pre><code>  &gt;&gt;&gt; update_t1_name = db.prepare(&#x27;UPDATE t1 SET name = $2 WHERE id = $1&#x27;)
  PREPARE stmt_001 AS UPDATE t1 SET name = $2 WHERE id = $1
  &gt;&gt;&gt; update_t1_name(1,&#x27;xxx&#x27;)
  EXECUTE _pstmt_001 (1,&#x27;xxx&#x27;)
</code></pre>
[1] <a href="https:&#x2F;&#x2F;github.com&#x2F;paulchakravarti&#x2F;pgwrap" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;paulchakravarti&#x2F;pgwrap</a>
[2] <a href="https:&#x2F;&#x2F;pypi.python.org&#x2F;pypi&#x2F;pgwrap" rel="nofollow">https:&#x2F;&#x2F;pypi.python.org&#x2F;pypi&#x2F;pgwrap</a>