2009-08-15 12 views
17

Ho un'applicazione python che apre una connessione al database che può rimanere in attesa per un ora, ma a volte il server del database si riavvia e mentre python ha ancora la connessione non funzionerà con l'eccezione OperationalError.Verificare che la connessione al database psycopg2 sia attiva

Quindi sto cercando un metodo affidabile per "eseguire il ping" del database e sapere che la connessione è attiva. Ho controllato una documentazione di psycopg2 ma non riesco a trovare nulla di simile. Certo che posso rilasciare alcune semplici istruzioni SQL come SELECT 1 e rilevare l'eccezione, ma spero che esista un metodo nativo, qualcosa come PHP pg_connection_status

Grazie.

risposta

8

pg_connection_status viene implementato utilizzando PQstatus. psycopg non espone quell'API, quindi il controllo non è disponibile. L'unico punto in cui psycopg chiama PQstatus è quando viene effettuata una nuova connessione e all'inizio dell'esecuzione. Quindi sì, sarà necessario emettere una semplice dichiarazione SQL per scoprire se la connessione è ancora lì.

+0

Sono giunto alla stessa conclusione durante la lettura delle fonti di psycopg2. Grazie. – HardQuestions

+0

Effettuerà la richiesta all'autore di psycopg per aggiungere tale funzionalità. – HardQuestions

+0

Vedi sotto la risposta di Jaymon. – sage88

30

Questa domanda è molto vecchio, ma ancora appare sullo ricerche di Google in modo da penso che sia importante sapere che l'istanza psycopg2.connection ha ora una closed attribute che verrà 0 quando la connessione è aperta, e maggiore di zero quando la connessione è chiuso. L'esempio che segue deve dimostrare:

import psycopg2 
import subprocess 

connection = psycopg2.connect(
    database=database, 
    user=username, 
    password=password, 
    host=host, 
    port=port 
) 

print connection.closed # 0 

# restart the db externally 
subprocess.check_call("sudo /etc/init.d/postgresql restart", shell=True) 

# this query will fail because the db is no longer connected 
try: 
    cur = connection.cursor() 
    cur.execute('SELECT 1') 
except psycopg2.OperationalError: 
    pass 

print connection.closed # 2 
+3

Hai provato ad uccidere le connessioni al database TCP handle (su Windows). 'connection.closed' purtroppo non cambierà valore. – Vyktor

+0

@Vyktor Hai ragione! Il problema è che la connessione di Python non sa che è stata interrotta fino a quando non tenta di comunicare con il db. Ho aggiornato l'esempio. La buona notizia è che è possibile avvolgere il codice di esecuzione della query per verificare la connessione in caso di errore e riconnettersi come appropriato. – Jaymon

+0

La mia connessione si è chiusa durante una query perché il database è stato riavviato, 'cur.execute ('SELECT 1')' ha lanciato un 'InterfaceError' nel mio caso con il messaggio' cursore già chiuso' – raphael

6

connection.closed non riflette una connessione chiusa/reciso dal server. Indica solo una connessione chiusa dal client utilizzando connection.close()

Per assicurarsi che una connessione sia ancora valida, leggere la proprietà connection.isolation_level. Ciò solleverà un OperationalError con pgcode == "57P01" nel caso in cui la connessione sia morta.

Questo aggiunge un po 'di latenza per un roundtrip al database, ma dovrebbe essere preferibile a un SELECT 1 o simile.

import psycopg2 
dsn = "dbname=postgres" 
conn = psycopg2.connect(dsn) 

# ... some time elapses, e.g. connection within a connection pool 

try: 
    connection.isolation_level 
except OperationalError as oe: 
    conn = psycopg2.connect(dsn) 

c = conn.cursor() 
c.execute("SELECT 1") 
+1

Testato con psycopg2 2.5.2 e psql 8.4 - isolamento il livello è sempre zero, non importa quale. –

Problemi correlati