2
\$\begingroup\$

I have written this code that connects to a mysql database. The function should be able to be used as a context manager - via with. It is working, but I am not sure if this is a great way of doing it.

conect.py

import os
import mysql.connector
from mysql.connector import errorcode
import contextlib
_CFG = {
 'user': os.getenv("MYSQL_USER"),
 'password': os.getenv("MYSQL_PASSWORD"),
 'host': os.getenv("MYSQL_SERVER"),
 'database': os.getenv("SENSOR_DB"),
 'raise_on_warnings': True
}
@contextlib.contextmanager
def _connect(db=None):
 if db:
 _CFG["database"] = db
 try:
 print("{usr} connecting to {db} on {host}.".format(
 usr=_CFG["user"],
 db=_CFG["database"],
 host=_CFG["host"]
 )
 )
 connection = mysql.connector.connect(**_CFG)
 yield connection
 except mysql.connector.Error as err:
 if err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
 print("Something is wrong with your user name or password")
 elif err.errno == errorcode.ER_BAD_DB_ERROR:
 print("Database does not exist")
 else:
 print(err)
 yield None
 else:
 connection.commit()
 finally:
 connection.close()
Peilonrayz
44.4k7 gold badges80 silver badges157 bronze badges
asked Jan 21, 2020 at 20:10
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$
  1. Obvious (dumb) point - I'd suggest using logging instead of print
  2. I would have some kind of builder for _CFG so I could choose if I use environment variables for configuration or something else
  3. Instead of str.format, you may want to use fstring: f"{_CFG["user"]} connecting to {_CFG["database"]} on {_CFG["host"]}."
  4. Instead of yield None you may want to reraise exception (from the docs, "If an exception is trapped merely in order to log it or to perform some action (rather than to suppress it entirely), the generator must reraise that exception"). Otherwise, your code will fail with a funny exception.
Toby Speight
87.9k14 gold badges104 silver badges325 bronze badges
answered Jan 22, 2020 at 17:28
\$\endgroup\$
3
  • \$\begingroup\$ I was wondering even if the _connect function acts as context manger , should I just call it at module level instead of using with inside a function, then the connection object will be available at multiple functions ? \$\endgroup\$ Commented Jan 26, 2020 at 18:43
  • \$\begingroup\$ @Ciastopiekarz I think that if you want to have a shared connection in multiple functions, you would rather not use a context manager at all, but some other patterns to handle this. But why would you want this? I would not bother unless I am sure there's some significant performance impact, but I don't think there would be. \$\endgroup\$ Commented Jan 27, 2020 at 10:25
  • \$\begingroup\$ Ok, cool thanks I tried yesterday and didn’t find any significant benefit so switched back. \$\endgroup\$ Commented Jan 27, 2020 at 10:27

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.