Friday, April 13, 2018

Python read config .ini and connect to a database

This is my first Python application.

There are some knowledge points inline with code.

..
The souce code is here, https://github.com/goodgoodwish/code_tip/blob/master/python/db.py .
.
import psycopg2 # import PostgreSQL database interface library.
import traceback
import sys
# Add PYTHONPATH, then we may import all the objects below this folder.
sys.path.insert(0,"/Users/charliezhu/git/bi-cloud/etl")
# import tool to parse .ini configuration file.
# See below link for the explaination and examples:
# http://www.postgresqltutorial.com/postgresql-python/connect/
# ConfigParser().read(), returns a 2 dimensional array, e.g.: [[a1,a2],[b1,b2], ...].
from etl.pipeline_core.config import Config
class DbTool(object):
# initialize a local field(object property/attribute). Constructor.
# config = Config.load("/Users/abc/aws/database.ini")
def __init__(self, ini_file): # put config constructor/initializer here?
self.config = Config.load(ini_file)
# Build a dictionary object to connect to a database.
# {'user': 'scala_user', 'password': '', 'host': 'localhost', 'database': 'scala_db'}
def db_config(self, db_name):
db = {}
params = self.config.settings.items(db_name)
for param in params:
db[param[0]] = param[1]
print(db)
return db
def app_name_db_passwd(self):
return self.config.get('app_name_db','password')
def test_query(conn, app_name_db_passwd):
# Use loan pattern to open a cursor, it'll be automatically closed after exit the scope.
with conn.cursor() as cur:
cur.execute("""SELECT table_catalog, table_schema, table_name
FROM information_schema.tables LIMIT 4
""")
rows = cur.fetchall()
print( "\nShow me the data:\n")
for row in rows:
print( "output: ", row[0], row[2])
def main():
try:
app_name_tool = DbTool("/Users/charliezhu/work/blastworks/aws/database.ini")
app_name_db = app_name_tool.db_config(db_name = 'local_db')
# Same loan pattern, but for database connection.
# **app_name_db, unpack dictionary to key value pairs arguments lists.
# see, https://docs.python.org/3.7/tutorial/controlflow.html#unpacking-argument-lists
with psycopg2.connect(**app_name_db) as conn:
test_query(conn, app_name_tool.app_name_db_passwd())
except:
traceback.print_exc()
print("I am unable to connect to the database")
# if run as the single script, run main method.
if __name__ == '__main__':
main()
view raw db.py hosted with ❤ by GitHub
.

Thursday, April 05, 2018

Thoughts and an example on Expression-Oriented Programming

Here is the code, to read password from .pgpass to connect o a PostgreSQL database.

object DbUtil {
  def dbPassword(hostname:String, port:String, database:String, username:String ):String = {
    // Usage: val thatPassWord = dbPassword(hostname,port,database,username)
    // .pgpass file format, hostname:port:database:username:password
    val passwdFile = new java.io.File(scala.sys.env("HOME"), ".pgpass")
    var passwd = ""
    val fileSrc = scala.io.Source.fromFile(passwdFile)
    fileSrc.getLines.foreach{line =>
      val connCfg = line.split(":")
      if (hostname == connCfg(0)
        && port == connCfg(1)
        && database == connCfg(2)
        && username == connCfg(3)
      ) { 
        passwd = connCfg(4)
      }
    }
    fileSrc.close
    passwd
  }

  def passwordFromConn(connStr:String) = {
    // Usage: passwordFromConn("hostname:port:database:username")
    val connCfg = connStr.split(":")
    dbPassword(connCfg(0),connCfg(1),connCfg(2),connCfg(3))
  }
}

Thoughts.

* foreach v.s.  map().filter()(0) . e.g.: List(1,2,3).filter(_ > 0)(0)
* var passwd, v.s.  val passwd inside of foreach.
* is it good to do chain of method style?

* how to break when find one, in a for loop ?

import util.control.Breaks._
breakable {
for (i <- 1 to 10) {
println(i)
if (i > 4) break // break out of the for loop }
}

* other improvement ?