Python-функция, которая принимает файловый объект или путь - PullRequest
12 голосов
/ 22 июля 2011

Я хочу написать функцию, которая принимает путь в виде строки или объект файла.Пока у меня есть:

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)

, где do_stuff принимает открытый файл объекта.

Есть ли лучший способ сделать это?Есть ли у with f as f: какие-либо последствия?

Спасибо!

Ответы [ 2 ]

14 голосов
/ 22 июля 2011

Странная вещь в вашем коде в том, что если ему передают открытый файл, он закрывает его.Это не хорошоКакой бы код ни открывал файл, он должен отвечать за его закрытие.Это делает функцию немного более сложной:

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()

Вы можете абстрагироваться от этого, написав свой собственный менеджер контекста:

@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)
3 голосов
/ 22 июля 2011

Вы можете сделать:

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

И затем, когда вы объявляете любую функцию, которая выполняет какие-либо операции с открытым файловым объектом:

@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

Редактировать 2: более подробная информация о декораторе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...