2011-07-21 14 views
11

Bir yolu ya da bir dosya nesnesi olarak kabul eden bir işlev yazmak istiyorum. Şimdiye kadar var:Dosya nesnesini veya yolu kabul eden Python işlevi

do_stuff açık dosya nesnesi alır
def awesome_parse(path_or_file): 
    if isinstance(path_or_file, basestring): 
     f = open(path_or_file, 'rb') 
    else: 
     f = path_or_file 
    with f as f: 
     return do_stuff(f) 

.

Bunu yapmanın daha iyi bir yolu var mı? with f as f:'un herhangi bir etkisi var mı?

Teşekkürler!

cevap

14

Kodunuzdaki tek şey, açık bir dosyadan geçtiyse, onu kapatacaktır. Bu iyi değil. Dosya açılırken hangi kodu açarsanız onu kapatmanız gerekir.

def awesome_parse(path_or_file): 
    if isinstance(path_or_file, basestring): 
     f = file_to_close = open(path_or_file, 'rb') 
    else: 
     f = path_or_file 
     file_to_close = None 
    try: 
     return do_stuff(f) 
    finally: 
     if file_to_close: 
      file_to_close.close() 

yapabilirsiniz kendi bağlam yöneticisi yazarak bu uzak soyut: Gerçi biraz daha karmaşık fonksiyonu yapar

@contextlib.contextmanager 
def awesome_open(path_or_file): 
    if isinstance(path_or_file, basestring): 
     f = file_to_close = open(path_or_file, 'rb') 
    else: 
     f = path_or_file 
     file_to_close = None 

    try: 
     yield f 
    finally: 
     if file_to_close: 
      file_to_close.close() 

def awesome_parse(path_or_file): 
    with awesome_open(path_or_file) as f: 
     return do_stuff(f) 
+0

Oh ... dosyayı kapatmaması gerektiğinde dosyayı yakala! Bunun olmasını kesinlikle istemiyorum. Teşekkürler! – TorelTwiddler

+1

Verim "verim" değil mi? –

+0

'@ contextlib.contextmanager' tam olarak ne yapar? Neden onsuz bir 'AttributeError: __exit__' olsun? Teşekkürler! –

3

Sen yapabilirdi:

def awesome_parse(do_stuff): 
    """Decorator to open a filename passed to a function 
     that requires an open file object""" 
    def parse_path_or_file(path_or_file): 
     """Use a ternary expression to either open the file from the filename 
      or just pass the extant file object on through""" 
     with (open(path_or_file, 'rb') 
       if isinstance(path_or_file, basestring) 
       else path_or_file) as f: 
      return do_stuff(f) 
    return parse_path_or_file 

Sonra da açık bir dosya nesne üzerinde şeyler yapar herhangi bir işlev bildirmek zaman:

@awesome_parse 
def do_things(open_file_object): 
    """This will always get an open file object even if passed a string""" 
    pass 

@awesome_parse 
def do_stuff(open_file_object): 
    """So will this""" 
    pass 

Edit 2: dekoratör Daha detaylı bilgi.

+0

Ah, evet, üzgünüm. Ben sadece 'süper' ile karıştırılmaması için 'awesome_parse' olarak değiştirdim. – TorelTwiddler

+0

Tamam, eşleşecek şekilde düzenleyeceğim. – agf

+1

Yanıtınız sanki @Ned Batchelder'ın cevap adresleriyle aynı anda kapanmış gibi görünüyor (dosyayı zamanından önce kapatarak). Ancak, dekoratör fikri gibi, ben de fikrinizi biraz kullanacağım! – TorelTwiddler

İlgili konular