"This inspection detects instance attribute definition outside __init__ method" PyCharm - python

I'm using the following class to connect and create a cursor within a firebase database:
class Firebird:
username= "..."
password= "..."
def __init__(self, archive):
self.archive = archive
def connect(self):
try:
self.connection = connect(dsn=self.archive, user=self.username, password=self.password)
except Error, e:
print "Failed to connect to database", e
exit(0)
And the PyCharm is warning me: "This inspection detects instance attribute definition outside init method", in the self.connection assign.
Is it a bad practice assign properties to the instance outside of __init__? In this case, what could i do?

Yes it's generally considered a good practice to explicitly define/declare all your attributes in the __init__ function, this way you have a quick list of all used (or unused) attributes in the class.
class Firebird:
username= "..."
password= "..."
def __init__(self, archive):
self.archive = archive
self.connection = None
def connect(self):
try:
self.connection = connect(dsn=self.archive, user=self.username, password=self.password)
except Error, e:
print "Failed to connect to database", e
exit(0)

Related

single database connection throughout the python application (following singleton pattern)

My Question is what is the best way to maintain the single database connection in the entire application? Using Singleton Pattern? How?
Conditions that are needed to be taken care of:
In case of multiple requests, I should be using the same connection
In case connection is closed, create a new connection
If the connection has timed-out, on new request my code should create a new connection.
The driver to my Database is not supported by the Django ORM. And due to same driver related issues, I am using pyodbc to connect to the database. Right now I am having below class for creating and managing the DB connections:
class DBConnection(object):
def __init__(self, driver, serve,
database, user, password):
self.driver = driver
self.server = server
self.database = database
self.user = user
self.password = password
def __enter__(self):
self.dbconn = pyodbc.connect("DRIVER={};".format(self.driver) +\
"SERVER={};".format(self.server) +\
"DATABASE={};".format(self.database) +\
"UID={};".format(self.user) +\
"PWD={};".format(self.password) + \
"CHARSET=UTF8",
# "",
ansi=True)
return self.dbconn
def __exit__(self, exc_type, exc_val, exc_tb):
self.dbconn.close()
But the issue with this approach is that it will create new database connection for each query. What will be the better way to do it following singleton pattern? The way I can think of will hold the reference to the connection if the connection is closed. Something like:
def get_database_connection():
conn = DBConnection.connection
if not conn:
conn = DBConnection.connection = DBConnection.create_connection()
return conn
What will be the best way to achieve this? Any suggestion/ideas/examples?
PS: I was checking about using weakref which allows to create weak references to objects. I think it will be good idea to use weakref along with singleton pattern for storing the connection variable. This way I won't have to keep the connection alive when DB is not in use. What you guys say about this?
For now, I am going ahead with the singleton class approach. Anyone seeing the potential flaws in this, feel to mention them :)
DBConnector class for creating a connection
class DBConnector(object):
def __init__(self, driver, server, database, user, password):
self.driver = driver
self.server = server
self.database = database
self.user = user
self.password = password
self.dbconn = None
# creats new connection
def create_connection(self):
return pyodbc.connect("DRIVER={};".format(self.driver) + \
"SERVER={};".format(self.server) + \
"DATABASE={};".format(self.database) + \
"UID={};".format(self.user) + \
"PWD={};".format(self.password) + \
"CHARSET=UTF8",
ansi=True)
# For explicitly opening database connection
def __enter__(self):
self.dbconn = self.create_connection()
return self.dbconn
def __exit__(self, exc_type, exc_val, exc_tb):
self.dbconn.close()
DBConnection class for managing the connections
class DBConnection(object):
connection = None
#classmethod
def get_connection(cls, new=False):
"""Creates return new Singleton database connection"""
if new or not cls.connection:
cls.connection = DBConnector().create_connection()
return cls.connection
#classmethod
def execute_query(cls, query):
"""execute query on singleton db connection"""
connection = cls.get_connection()
try:
cursor = connection.cursor()
except pyodbc.ProgrammingError:
connection = cls.get_connection(new=True) # Create new connection
cursor = connection.cursor()
cursor.execute(query)
result = cursor.fetchall()
cursor.close()
return result
class DBConnector(object):
def __new__(cls):
if not hasattr(cls, 'instance'):
cls.instance = super(DBConnector, cls).__new__(cls)
return cls.instance
def __init__(self):
#your db connection code in constructor
con = DBConnector()
con1 = DBConnector()
con is con1 # output is True
Hope, above code will helpful.

Managing a database connection with a global, global name disappears

class MyAddon(pyxbmct.AddonDialogWindow):
def __init__(self, title=''):
super(MyAddon, self).__init__(title)
self.mysql_connect()
self.populate()
def populate(self):
categories = self.read_data()
def read_data(self):
query = ("SELECT category FROM test")
cursor = connection.cursor()
categories = cursor.execute(query)
return categories
def mysql_connect(self):
global connection
try:
connection = mysql.connector.connect(**config).cursor()
except mysql.connector.Error as err:
if err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
xbmc.executebuiltin('Notification(Error!, Bad user name of password)')
elif err.errno == errorcode.ER_BAD_DB_ERROR:
xbmc.executebuiltin('Notification(Error!, Database does not exist)')
else:
xbmc.executebuiltin('Notification(Error!, {0})'.format(err))
I'm developing a Python add-on for Kodi. I get a Global name 'connection' is not defined error when trying to use a global variable for the database connection. I cannot read the global variable connection from the read_data function. I'm sure this is not a forward reference problem because I tested it that way.
The purpose of using a global variable for the connection is to reuse the connection in all the functions without creating a new connection every time.
It may be that Kodi does something funky with namespaces or your instances are pickled; when unpickled the global will be gone. Another problem with a global like this is that the connection might be lost at some point.
I'd restructure the code to have a method that returns a connection, and use that in all methods that require a connection. Make the connection method a classmethod and allow for the connection to be gone:
class MyAddonConnectionFailed(Exception): pass
def read_data(self):
query = ("SELECT category FROM test")
try:
conn = self.connect()
except MyAddonConnectionFailed:
# connection failed; error message already displayed
return []
cursor = conn.cursor()
categories = cursor.execute(query)
return categories
_connection = None
#classmethod
def connect(cls):
if cls._connection and cls._connection.open:
return cls._connection
try:
cls._connection = mysql.connector.connect(**config).cursor()
return cls._connection
except mysql.connector.Error as err:
if err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
xbmc.executebuiltin('Notification(Error!, Bad user name of password)')
elif err.errno == errorcode.ER_BAD_DB_ERROR:
xbmc.executebuiltin('Notification(Error!, Database does not exist)')
else:
xbmc.executebuiltin('Notification(Error!, {0})'.format(err))
raise MyAddonConnectionFailed
I'm raising an exception in the connect classmethod; you'll need to decide how you want to handle the case where your database is misconfigured or can't connect. Displaying an error message is not enough. You could still call self.connect() from the __init__ method to signal this problem early of course.

Python Pika callback is not working with SelectConnection inside a class

I am trying to create a simple Python Pika SelectConnection and it seems that I am not able to open a connection using the on_open_callback and I don't get anything from te on_open_error_callback either. Can someone suggest what might be causing the problem?
import pika
class RabbitmqTransport(object):
def __init__(self):
self._connection = None
self._channel = None
self._connect()
def on_connection_open(self):
print "connection created"
def on_connection_open_error(self):
print "connection open error"
def _connect(self):
# Setup RabbitMQ connection
credentials = pika.PlainCredentials('guest','guest')
parameters = pika.URLParameters('amqp://guest:guest#localhost:5672/%2F')
print "Creating Connection"
self._connection = pika.SelectConnection(parameters=parameters,on_open_callback=self.on_connection_open,on_open_error_callback=self.on_connection_open_error)
print self._connection.connection_state
print dir(self._connection)
print self._connection.is_open
r = RabbitmqTransport()
Found the problem, I added the line bellow and then connection was opened and the callback worked.
self._connection.ioloop.start()

How to deal with an unavailable host (ConnectionRefusedError) in a proxy class

I have a very basic proxy class (a friend who helped me coding it insists it's a decorator class instead) for python-mpd2.
The class looks like this
import mpd
class MPDProxy:
def __init__(self, host="localhost", port=6600, timeout=10):
self.client = mpd.MPDClient()
self.host = host
self.port = port
self.client.timeout = timeout
self.connect(host, port)
def __getattr__(self, name):
return self._call_with_reconnect(getattr(self.client, name))
def connect(self, host, port):
self.client.connect(host, port)
def _call_with_reconnect(self, func):
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except mpd.ConnectionError:
self.connect(self.host, self.port)
return func(*args, **kwargs)
return wrapper
mpd_proxy = MPDProxy()
This works well so far, as long as there is an mpd host available to connect to. If there is no mpd server, I get
ConnectionRefusedError: [Errno 111] Connection refused
I'm looking for good patterns to deal with this Exception
Can you think of an elegant way to prevent the program to crash, when there is no host available?
Should I catch the exception within the proxy or outside, whenever the proxy is called?
Is a string "Host not available" (or similar) as a return value a good idea or can a method/function calling the proxy be informed in a better way?
Can you think of an elegant way to prevent the program to crash, when there is no host available?
try ... except ;)
Should I catch the exception within the proxy or outside, whenever the proxy is called?
The question you should ask yourself is "who is *able* to deal with that exception?"
Obviously, the proxy can't to anything sensible to "fix" ConnectionRefusedError. So it has to be handled at upper levels.
Is a string "Host not available" (or similar) as a return value a good idea or can a method/function calling the proxy be informed in a better way?
Bad idea. The normal way of informing "upper levels" than an exception has occurred is to raise an exception. Or to let a raised exception propagate up.
Concretely:
class MPDProxy:
def _call_with_reconnect(self, func):
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except mpd.ConnectionError:
self.connect(self.host, self.port)
# ^^^^^^ This lime might raise `ConnectionRefusedError`
# as there is no `except` block around, this exception
# is automatically propagated
return func(*args, **kwargs)
return wrapper
try:
mpd_proxy = MPDProxy()
r = mdp_proxy._call_with_reconnect(whatever)
except ConnectionRefusedError:
do_somesible_sensible()

Python: MySQL connection is open, but can't create cursor

I'm trying to open a cursor to a MySQL-DB. But I'm getting this error:
'NoneType' object has no attribute 'cursor'
Here is a small sourcecode:
class Sample:
def __init__(self):
self.conn = None
self.value = self.setValue()
def connect(self):
self.conn = MySQLdb.connect(...)
#cursor = self.conn.cursor()
#cursor.execute("SELECT ...")
#value = str(cursor.fetchone()[0])
#raise Exception(value)
#cursor.close() <- here everything is working fine
def setValue(self):
if (self.conn == None):
self.connect()
#raise Exception(self.conn.open)
cursor = self.conn.cursor() # ERROR: 'NoneType' object has no attribute 'cursor'
...
If I use the exception I get a 1 ... connection is open.
And if I do the cursor creation and the SQL statement in the 'connect' function everything is working well.
The strange this is, everything looks correct and for some other connections with the same functions everything is working well, too. I don't know how to solve this error. I hope someone can point me in the right direction.
I would change the statement that checks if the connection is open to both check if conn is none as well as if the connection is open. And because you always execute the setValue function I would recommend that you call the connect inside the__init__ function.
class Sample:
conn = None
def __init__(self):
self.connect()
self.value = self.setValue()
self.close()
def connect(self):
self.conn = MySQLdb.connect(...)
def close(self):
if self.conn:
self.conn.close()
def setValue(self):
if not self.conn and not self.conn.open:
self.connect()
cursor = self.conn.cursor()
Also, remember that with the Python MySQL Connector you need to call commit after you execute a insert or update statement.
cur = self.conn.cursor()
cur.execute("...")
self.conn.commit()

Categories