How to avoid writing "MySQLdb.connect" again and again? - python

I wonder if there is a way to avoid writing MySQLdb.connect(host='localhost', user='xyz', password='xyz', db='xyz')
again and again in Python?
Example:
def Add_New_User(self):
self.db = MySQLdb.connect(host='localhost', user='xyz', password='xyz', db='xyz')
self.cur = self.db.cursor()
after two or three lines (when new def is required and a lot of def is required), I need to write all over again the same string many times
def Add_New_User(self):
self.db = MySQLdb.connect(host='localhost', user='xyz', password='xyz', db='xyz')
self.cur = self.db.cursor()
I hope that there is a way to call it in a simple way, like a connection code written and saved in, e.g., MyConString.py then in the new def say, index.py, I would simply call the function MyConString.

Create a function called connection:
def conn(database):
import mysql.connector
connection = mysql.connector.connect(host='localhost',
database=database,
user='root',
password='yourpass')
cursor = connection.cursor(buffered=True)
return connection, cursor
Now, whenever you have to connect in any function do this:
def insert():
connection_data = conn("mydatabase")
connection = connection_data[0]
cursor = connection_data[1]
cursor.execute("show tables;")
connection.commit()
connection.close()
You can even make an entirely new script for functions that are repeatedly used to keep your main file clean.
Then you can just add import connections.py(say, that is your file name which contains conn() function)
# This is your main.py
import connections
def insert():
connection_data = connections.conn("mydatabase")
connection = connection_data[0]
cursor = connection_data[1]
cursor.execute("show tables;")
connection.commit()
connection.close()
Hope this helped!

Related

What is the right way to design Python / SQLite application without repeating connection part?

im trying to develop a simple application where multiple business objects are saved to the sqlite database. I have several business objects for which I want to program save/update/delete methods. For each of the classes and methods within those classes I always create a new connection. For example:
import sqlite3
db = "mydb.db"
class BusinessObject1:
...
def save_to_db(self, db):
conn = sqlite3.connect(db)
cur = conn.cursor()
with conn:
cur.execute("...")
def delete_from_db(self, db):
conn = sqlite3.connect(db)
cur = conn.cursor()
with conn:
cur.execute("...")
class BusinessObject2:
...
def save_to_db(self, db):
conn = sqlite3.connect(db)
cur = conn.cursor()
with conn:
cur.execute("...")
def delete_from_db(self, db):
conn = sqlite3.connect(db)
cur = conn.cursor()
with conn:
cur.execute("...")
It doesn't feel like a good design solution (not DRY). Can someone propose a better design for this? I have around 20 Business objects and 4-8 methods for each and a record table where all these objects are included. Typing conn=sqlite3.connect(db) every time simply cannot be the right way. And if I'll decide to change to MySQL or PostgreSQL I would need to refactor the whole project.
Thanks!
Then you might want to separate the connection handler from the class object or you can do as the comment above suggesting to put the connection inside the class constructor.
If for some reason you can't do both you can still add a staticmethod to your class that will handle the connection. It's not ideal but it's still better than your solution:
#staticmethod
def create_connection(db_file):
conn = None
try:
with sqlite3.connect(db_file) as conn:
return conn
except sqlite3.Error as e:
print("Can't connect to database, error:", e, sep="\n")
return conn
Then you add a parameter to your other methods which will be the returned create_connection method:
def save_to_db(self, connection):
cur = connection.cursor()
cur.execute("...")
This way you can separate your connect object from your class object:
if __name__ == "__main__":
conn = BusinessObject1.create_connection(db)
b1 = BusinessObject1(...)
b1.save_to_db(conn)

Python and MySQL - Weak Reference Error when Executing Query

I am new to Python and MySQL and having some trouble with a connection class that I am using to execute queries.
Here is my what I have so far:
class DbConnection:
def __init__(self):
db = mysql.connector.connect(
host=cfg.mysql["host"],
user=cfg.mysql["user"],
passwd=cfg.mysql["passwd"],
database=cfg.mysql["database"]
)
self.cursor = db.cursor()
def query(self, sql):
self.cursor.execute(sql)
return self.cursor.fetchall()
test = DbConnection()
test.query('SELECT * FROM DaycareDogs')
When I try and run this (or any query) I am getting "ReferenceError: weakly-referenced object no longer exists".
I am very new to coding and this is my first real project so am learning on the fly.
Is there something I am missing? I have seen a few other similar problems and did what was recommended but still no luck.
Any advice?
Thanks!
Try making the database connection a property of the class, by also adding self in front of it
class DbConnection:
def __init__(self):
self.db = mysql.connector.connect(
host=cfg.mysql["host"],
user=cfg.mysql["user"],
passwd=cfg.mysql["passwd"],
database=cfg.mysql["database"]
)
self.cursor = self.db.cursor()
def query(self, sql):
self.cursor.execute(sql)
return self.cursor.fetchall()
test = DbConnection()
test.query('SELECT * FROM DaycareDogs')
Since the variable db is in the local scope, when the 'init' constructor ends, the variable will be destroyed, therefore the connection

Should I use a single database connection for my PySIde application?

I am writing a GUI application with PySide. It has a few tables that get populated with data from a database, by pushing the corresponding buttons.
I thought of using a single database connection when the application starts and pass conn and cursor as variables in any functions that concern the database:
import sqlite3
database_fullpath = self.get_database_fullpath()
conn = sqlite3.connect(database_fullpath)
cursor = conn.cursor()
def populate_table(self, conn, cursor):
# do something
Maybe, I should connect to the database everytime it's needed:
import sqlite3
def populate_table(self):
database_fullpath = self.get_database_fullpath()
conn = sqlite3.connect(database_fullpath)
cursor = conn.cursor()
# do something
I am not sure which is the right approach and what the advantages of the different methods are.
One approach might be to provide a helper class that reuses the connection if available and reconnects if not:
class SqliteDb(object):
def __init__(self, db_fullpath):
self.db_fullpath = db_fullpath
self.conn = None
def connect(self):
self.conn = sqlite3.connect(self.db_fullpath)
def cursor(self, factory=sqlite3.Cursor):
try:
return self.conn.cursor(factory=factory)
except (AttributeError, sqlite3.ProgrammingError):
self.connect()
return self.conn.cursor(factory=factory)
def close(self):
self.conn.close()
Then in your code:
database_fullpath = self.get_database_fullpath()
sqlite_db = SqliteDb(database_fullpath)
cursor = sqlite_db.cursor()

Python, sharing mysql connection in multiple functions - pass connection or cursor?

I am opening mysql connection in the main function and use that connection in multiple functions called by the main function.
Is there anything wrong with passing cursor from main function instead of passing the connection?
I.e.:
Pass in cursor from main function
def main():
conn = pymysql.connect(...)
with conn as cursor:
func1(cursor)
func2(cursor)
conn.close()
def func1(cursor):
cursor.execute('select ...')
def func2(cursor):
cursor.execute('insert ...')
Pass in connection from main function
def main():
conn = pymysql.connect(...)
func1(conn)
func2(conn)
conn.close()
def func1(conn):
with conn as cursor:
cursor.execute('select ...')
def func2(conn):
with conn as cursor:
cursor.execute('insert ...')
The answer comes from Law of Demeter: Pass cursor.
This also leads to a slightly shorter code. In this case, it's pretty trivial, but sometimes it may be a lot (e.g., passing a database name vs. passing a cursor).

Using cursors with mysqldb and flask

It's more of a theoratical question but i have been trying to find a correct answer of it for hours and yet i have't arrived at a solution. I have a big flask app and it contains multiple routes.
#app.route('/try'):
#app.route('/new'):
and many others. I am using MySQLdb for database purpose. Before i was having this in the starting of the application.
import MySQLdb as mysql
db = mysql.connect('localhost', 'root', 'password', 'db')
cursor = db.cursor()
It works fine but after a time, it generates a error "Local Variable 'cursor' referenced before assignment.". This may be due to the reason that after a time mysql closes a connection. So, i entered
cursor=db.cursor() in every route function and close it afer i have done the processing like this:
db = mysql.connect('localhost', 'root', 'password', 'db')
#app.route('/')
def home():
cursor=db.cursor()
...some processing...
cursor.close()
return render_template('home.html')
#app.route('/new')
def home_new():
cursor=db.cursor()
...some processing...
cursor.close()
return render_template('homenew.html')
Now i want to ask is this approach right? Should i define a cursor for each request and close it?
This is how I have my MySQLdb setup
def requestConnection():
"Create new connection. Return connection."
convt = cv.conversions.copy()
convt[3] = int
convt
conn = db.connect(host=c.SQL_HOST, port=c.SQL_PORT, user=c.SQL_USER, passwd=c.SQL_PASSWD, db=c.SQL_DB, conv=convt, use_unicode=True, charset="utf8")
return conn
def requestCursor(conn):
return conn.cursor(db.cursors.DictCursor)
Then, at the start of every SQL function I do this:
def executeQuery(query):
"Execute a given query. Used for debug purpouses."
conn = requestConnection()
cur = requestCursor(conn)
cur.execute(query)
r = cur.fetchall()
cur.close()
conn.close()
return r
I change conversions because I had to change int values in DB from Float to int due to my work, but you can skip this step.
If not, you need to import this:
import MySQLdb as db # https://github.com/farcepest/MySQLdb1
import MySQLdb.converters as cv
Hope it helps!

Categories

Resources