2014-04-28 3 views
14

Sto usando Boto per connettermi ad Amazon S3 nel mio programma Python. Sono in grado di aprire una connessione e caricare file in un bucket. Ho pensato che avrei dovuto chiudere la connessione per liberare risorse e, cosa più importante, per evitare qualsiasi rischio per la sicurezza di lasciare una connessione aperta in giro. Presumo che dovrei chiamare il metodo close(). Ma ho provato questo come segue: 1. Aprire la connessione. 2. Chiudere la connessione. 3. Carica il file nel secchio.Come chiudere la connessione Boto S3?

Ho pensato che il passaggio 3 sarebbe fallito, ma il caricamento ha funzionato! Quindi cosa fa close()? Se in realtà non chiude la connessione, cosa dovrei usare al posto di close()? O è semplicemente inutile chiudere la connessione?

Ho cercato la risposta nel Boto tutorial, nel Boto API reference e nel this StackOverflow post, ma finora non ho avuto fortuna.

Grazie per il vostro aiuto.

risposta

6

Il passaggio 3 ha funzionato perché boto ha un codice che riaprirà automaticamente le connessioni chiuse e riproverà le richieste sugli errori. C'è poco da guadagnare chiudendo manualmente le connessioni boto perché sono solo connessioni HTTP e si chiuderanno automaticamente dopo alcuni minuti di inattività. Non mi preoccuperei di provare a chiuderli.

2

Sotto le copertine, boto utilizza httplib. Questa libreria client supporta HTTP 1.1 Keep-Alive, quindi può e deve mantenere aperto il socket in modo che possa eseguire più richieste sulla stessa connessione.

connection.close() non chiude effettivamente le prese sottostanti. Invece, rimuove il riferimento al pool sottostante delle connessioni httplib, che consente al garbage collector di eseguirle, e in quel momento avviene la chiusura effettiva del socket.

Ovviamente, è anche possibile lasciare che il garbage collector funzioni mantenendo un riferimento alla connessione stessa. Ma ci sono vantaggi prestazionali nel riutilizzare la connessione boto (per esempio vedere la nota Keep-Alive sopra).

Fortunatamente, nella maggior parte dei casi, non è necessario chiamare lo connection.close() in modo esplicito. Per maggiori dettagli su un caso in cui devi chiamare da vicino, vedi la mia risposta a the StackOverflow post che è collegata nella domanda.

0

C'è almeno un'istanza in cui lasciare aperta questa connessione può causare un errore. La risposta sopra mi ha portato alla soluzione. Sotto, addUnverifiedEmail inserisce un inserto DB RDS AWS. Pertanto, la connessione boto3 è ancora in ambito e attiva quando si tenta di eseguire l'inserimento. Questo è dal mio Lambda (pitone).

boto3.client.sign_up(
       ClientId='xxxxxxxxxxxxxxxxxxxxxxxxxx', 
       Username=self._user['email'], 
       Password=self._user['password'], 
       UserAttributes=attributes 
) 
dbUserInstance.addUnverifiedEmail(self._user['email']) 

Risultato (errore 1205 Blocco tempo di attesa superato). Sotto, addUserToCognito crea la connessione boto3 e cade fuori dall'ambito prima dell'inserto.

self.addUserToCognito() 
dbUserInstance.addUnverifiedEmail(self._user['email']) 

L'inserimento è riuscito dopo aver apportato questa modifica. Fortunatamente per me, addUnverifiedEmail è stata l'ultima chiamata di funzione all'interno di addUserToCognito, quindi è stato facile spostarla all'esterno. Altro, più complesso, codice potrebbe non avere la stessa abilità. Quindi, client.close() in realtà non chiude la connessione e tenerla chiusa potrebbe essere un grosso difetto.