How to check the connection alive in python?

Question:

I make project read RFID tag using python on raspberry pi and using reader RDM880.

My idea is to take the time in and time out to check with the staff to work on time or not.

I try to add card_ID, time_in, time_out to local mysql and remote mysql (IP: 192.168.137.1) using python.

It has the same table in remote and local mysql.

If mysql remote is broken, I want only add to local mysql.

Here is my code:

import serial
import time
import RPi.GPIO as GPIO
import MySQLdb
from datetime import datetime
from binascii import hexlify
serial=serial.Serial("/dev/ttyAMA0",                    
                  baudrate=9600,                     
                  parity=serial.PARITY_NONE,                    
                  stopbits=serial.STOPBITS_ONE,                    
                  bytesize=serial.EIGHTBITS,
                  timeout=0.1) 
db_local = MySQLdb.connect("localhost","root","root","luan_van") #connect local
db = MySQLdb.connect("192.168.137.1", "root_a","","luan_van") #connect remote
ID_rong = 128187 # reader respone if no card
chuoi= "xAAx00x03x25x26x00x00xBB"
def RFID(str): #function read RFID via uart 
      serial.write(chuoi)
      data = serial.readline()
      tach_5 = data[5]
      tach_6 = data[6]
      hex_5 = hexlify(tach_5)
      hex_6= hexlify(tach_6)
      num_5 = int(hex_5,16)
      num_6 = int(hex_6,16)
      num_a = num_5 * 1000 + num_6
      if(num_a != ID_rong):
            tach_7 = data[7]
            tach_8 = data[7]
            hex_7 = hexlify(tach_7)
            hex_8= hexlify(tach_8)
            num_7 = int(hex_7,16)
            num_8 = int(hex_8,16)
            num = num_8 + num_7 * 1000 + num_6 * 1000000 + num_5 * 1000000000
      else:
            num = num_5 * 1000 + num_6
      return num
def add_database(): # add card_ID and time_in to remote mysql
      with db:
           cur = db.cursor()
           cur.execure("INSERT INTO tt_control(Card_ID,Time_in) VALUES ('%d',NOW()) " %num)
           return
def add_database_local(): # add card_ID and time_in to remote mysql
      with db_local:
           cur = db_local.cursor()
           cur.execure("INSERT INTO tt_control(Card_ID,Time_in) VALUES ('%d',NOW()) " %num)
           return
def have_ID(int): #check ID in table tt_control
       with db_local:
           cur = db_local.cursor(MySQLdb.cursors.DictCursor)
           cur.execute("SELECT * FROM tt_control WHERE Card_ID = '%d'" %num)
           rows = cur.fetchall()
           ID=""
           for row in rows:
               ID = row['Card_ID']
       return ID
def add_time_out(): #add time out to remote mysql
       with db:
           cur = db.cursor(MySQLdb.cursors.DictCursor)
           cur.execute("UPDATE tt_control SET Time_out = NOW() WHERE Card_ID = '%d'" %num)
       return
def add_time_out_local(): #add time out to local mysql
       with db_local:
           cur = db_local.cursor(MySQLdb.cursors.DictCursor)
           cur.execute("UPDATE tt_control SET Time_out = NOW() WHERE Card_ID = '%d'" %num)
       return

  def add_OUT(): #increase Card_ID to distinguish second check
     with db:
           cur = db.cursor(MySQLdb.cursors.DictCursor) 
           cur.execute("UPDATE tt_control SET Card_ID = Card_ID + 1 WHERE Card_ID = '%d'" %num)
     return
  def add_OUT_local(): #increase Card_ID to distinguish second check
     with db_local:
           cur = db_local.cursor(MySQLdb.cursors.DictCursor) 
           cur.execute("UPDATE tt_control SET Card_ID = Card_ID + 1 WHERE Card_ID = '%d'" %num)
     return
  while 1:
     num = RFID(chuoi)
     time.sleep(1)
     Have_ID =have_ID(num)
     if(num != ID_rong):
            if(Have_ID ==""):
                 add_database() #---> it will error if remote broken, how can i fix it?
                 add_database_local()
            else:
                 add_time_out() #---> it will error if remote broken, how can i fix it? I think connection alive can fix, but I don't know
                 add_time_out_local()
                 add_OUT()
                 add_OUT_local() #---> it will error if remote broken, how can i fix it?
Asked By: nistelrooy41001662

||

Answers:

You have a couple choices:

(not as good) Ping the server regularly to keep the connection alive.

(best) Handle the MySQLdb exception when calling cur.execute by re-establishing your connection and trying the call again. Here’s an excellent and concise answer for how to do just that. From that article, you handle the exception yourself:

def __execute_sql(self,sql,cursor):
    try:
        cursor.execute(sql)
        return 1
    except MySQLdb.OperationalError, e:            
        if e[0] == 2006:
            self.logger.do_logging('info','DB', "%s : Restarting db" %(e))
            self.start_database()
            return 0

(lastly) Establish a new database connection just before you actually call the database entries. In this case, move the db and db_local definitions into a function which you call just before your cursor. If you’re making thousands of queries, this isn’t the best. However, if it’s only a few database queries, it’s probably fine.

Answered By: VooDooNOFX

I use the following method:

def checkConn(self):
    sq = "SELECT NOW()"
    try:
        self.cur.execute( sq )
    except pymysql.Error as e:
        if e.errno == 2006:
            return self.connect()
        else:
            print ( "No connection with database." )
            return False
Answered By: Al Berger

I used a simple technique. Initially, I connected to DB using:

conect = mysql.connector.connect(host=DB_HOST, user=DB_USER, password=DB_PASS, database=DB_NAME)

Whenever I need to check if the DB is still connected, I used a line:

conect.ping(reconnect=True, attempts=3, delay=2)

This will check if the DB connection is still alive. If not, it will restart the connection which solves the problem.

It just makes sense not to use a status checker function before executing a SQL. Best practice shall handle the exception afterward and reconnect to the server.

Since the client library is always on the client side, there is no way to know the server status (connect status does depend on server status of course) unless we ping it or connect it.

Even if you ping the server and make sure the connection is fine and let the code execute down to the following line, the connection theoretically still could be down within that glimpse of time. So it’s still not guaranteed that you will have a good connection right after you check the connection status.

On the other hand, ping is as expensive as most operations. If your operation fails because of a bad connection, then it’s as good as using the ping to check the status.

Considering these, why bother to use ping or other no-matter built-in or not-built-in functions to check the connection status? Just execute your command as if it is up, then handle the exception in case it is down. This might be the reason the mysqlclient library does not provide a built-in status checker in the first place.

Answered By: wholehope
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.