title: How do I handle connection errors in my database class when using `with` in Python?
body: <p>In the following Database class if the connection fails my error is printed. But, a system error is also printed because the <code>__exit__</code> code fires.</p>
  
  <blockquote>
    <p>AttributeError: 'Database' object has no attribute '_conn'</p>
  </blockquote>
  
  <p>How should I handle this type of situation?<br>
  <code>try/except</code> Or is there a better way?</p>
  
  <pre><code>import psycopg2
  import mysecrets as ms
  from time import time
  
  
  class Database(object):
      def __init__(self, localhost=False):
          try:
              print(f"ATTEMPTING DATABASE CONNECTION")
              self._conn = psycopg2.connect(
                  f"""
                  dbname =    {ms.LOCALDB_NAME if localhost else ms.DB_NAME}
                  port =      {ms.LOCALDB_PORT if localhost else ms.DB_PORT}
                  user =      {ms.LOCALDB_USER if localhost else ms.DB_USER}
                  password =  {ms.LOCALDB_PASS if localhost else ms.DB_PASS}
                  host =      {ms.LOCALDB_HOST if localhost else ms.DB_HOST}
                  """
              )
              self._cursor = self._conn.cursor()
              print(f"CONNECTED TO DATABASE\n")
          except Exception as error:
              print(f"UNABLE TO CONNECT TO DATABASE\n{error}")
  
      def __enter__(self):
          return self
  
      def __del__(self):
          self.connection.close()
  
      def __exit__(self, exc_type, exc_value, traceback):
          self.connection.close()
  
      @property
      def connection(self):
          return self._conn
  
      @property
      def cursor(self):
          return self._cursor
  
      def commit(self):
          self.connection.commit()
  
      def query(self, sql, params=None):
          self.cursor.execute(sql, params or ())
  
      def fetchall(self):
          return self.cursor.fetchall()
  
      def fetchone(self):
          return self.cursor.fetchone()
  
  
  if __name__ == "__main__":
      start_time = time()
  
      with Database() as db:
          elapsed_time = round(time() - start_time, 2)
          print(f"Testing database connection took {elapsed_time} seconds.")
  </code></pre>