# Database Connections in Python

> A Python application connects to the database (creates a database handle) by calling the Database method `connect()`. The database must have been previously opened, possibly in a different process if the database is in shared memory. For example:

>         db = exdb.open_database("myopendb", dict)
>         con = db.connect();

> The `db.connect()` returns a database connection that is used in subsequent calls to database APIs. Note that all applications must create a separate connection for each thread (task) that accesses the database; database connections cannot be shared between different threads or tasks.

> Applications should disconnect from the database once the database connection is no longer needed to allow the database runtime to “de-allocate” internal memory used to maintain the connection. A Python application disconnects from the database by calling `con.close()` The database cannot be destroyed (closed) until all active connections are closed.

> ## Example

> Typical application code to connect to an in-memory database could look like the following:

>         db = exdb.open_database("myopendb", dict)
>         con = db.connect();
>         ...
>         con.close()
>         db.close()

> ## Asynchronous Distributed Connections

> It is possible to process multiple SQL queries on database shards in parallel using the `exdb.connect()` method to connect to an AsyncDistributedSqlEngine. Then the `execute()` method is used to execute SQL statements on multiple shards. For example, the following code snippet creates a connection to an AsyncDistributedSqlEngine, creates SQL statement strings and arguments vectors, then executes the statements in parallel on 4 database shards and prints out the results.

>         nWorkers = 4

>         nodes = ("localhost:5001", "localhost:5002")

>         conn = self.exdb.connect(nodes=nodes, async=True, nWorkers=nWorkers)

>         q = ["INSERT INTO MyTable(pk, value, u2, i1, i2, i4, i8, flt, dbl) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"]*nWorkers

>         args = []
>         for i in xrange(nWorkers):
>             args.append((i*100, 'str%s' % i, i, i, i, i, i, i*100, i*100.9))

>         r = conn.execute(q, args)
>         print "len(r)=", len(r)
>         for k in range(len(r)):
>             pprint.pprint(r[k])