2010-09-22 9 views
25

Devo aprire un oggetto simile a file in python (è una connessione seriale tramite/dev /) e quindi chiuderlo. Questo è fatto più volte in diversi metodi della mia classe. Come stavo facendo era aprire il file nel costruttore e quindi chiuderlo nel distruttore. Sto ottenendo strani errori e penso che abbia a che fare con il garbage collector e così, non sono ancora abituato a non sapere esattamente quando i miei oggetti vengono cancellati = \Implementazione dell'uso di "con object() come f" nella classe personalizzata in python

Il motivo per cui stavo facendo questo è perché devo usare tcsetattr con una serie di parametri ogni volta che lo apro e diventa fastidioso fare tutto ciò dappertutto. Quindi voglio implementare una classe interna per gestire tutto ciò che così posso usarlo facendo
with Meter('/dev/ttyS2') as m:

che cercavo in linea e non sono riuscito a trovare una buona risposta su come è implementata la sintassi with. Ho visto che utilizza i metodi __enter__(self) e __exit(self)__. Ma tutto ciò che devo fare è implementare questi metodi e posso usare la sintassi? O c'è dell'altro?

Esiste un esempio su come eseguire questa o alcune documentazioni su come è già stato implementato su oggetti file che posso visualizzare?

risposta

36

Coloro i metodi sono praticamente tutto ciò che serve per far funzionare l'oggetto con l'istruzione with.

In __enter__ è necessario restituire l'oggetto file dopo averlo aperto e configurato.

In __exit__ è necessario chiudere l'oggetto file. Il codice per scriverlo sarà nel corpo della dichiarazione with.

class Meter(): 
    def __init__(self, dev): 
     self.dev = dev 
    def __enter__(self): 
     #ttysetattr etc goes here before opening and returning the file object 
     self.fd = open(self.dev, MODE) 
     return self.fd 
    def __exit__(self, type, value, traceback): 
     #Exception handling here 
     close(self.fd) 

meter = Meter('dev/tty0') 
with meter as m: 
    #here you work with the file object. 
    m.read() 
+1

'def __enter __ (self): return self' se si desidera un riferimento a' Meter' nel blocco with. – Morgoth

3

Il primo colpo di Google (per me) spiega abbastanza semplice:

http://effbot.org/zone/python-with-statement.htm

e il PEP spiega più precisamente (ma anche più verboso):

http://www.python.org/dev/peps/pep-0343/

+1

In realtà ho visto quelli e non pensavo che nessuno di loro fosse molto chiaro. Il primo dice più o meno "Ci sono metodi chiamati \ __ enter__ e \ __ exit__" e spiega poco o nulla su di loro. E il PEP parla praticamente della necessità della nuova sintassi – Falmarri

+0

No, è semplice con esempi e spiegazioni. Hai bisogno di leggerlo di nuovo; questa non è una caratteristica complessa. –

11

più semplice può essere quella di utilizzare il modulo standard di Python biblioteca contextlib:

import contextlib 

@contextlib.contextmanager 
def themeter(name): 
    theobj = Meter(name) 
    yield theobj 
    theobj.close() # or whatever you need to do at exit 

Questo non ha Meter sé un gestore contesto (e quindi non è invasivo a quella classe), ma piuttosto " decora "(non nel senso della" sintassi del decoratore "di Python, ma piuttosto quasi, ma non del tutto, nel senso dello schema di progettazione del decoratore ;-) con una funzione di fabbrica themeter quale è un gestore di contesto (che il contextlib.contextmanager decoratore costruisce da t lui "single- yield" funzione di generatore che scrivi) - questo lo rende così molto più facile separare la condizione di entrata e di uscita, evita l'annidamento, & c.

Problemi correlati