Откат на стандартный вывод, если имя файла не указано - PullRequest
4 голосов
/ 23 марта 2012

У меня есть скрипт, который принимает в качестве аргумента имя файла, а затем открывает его и записывает некоторые вещи.

Я использую оператор with:

with open(file_name, 'w') as out_file:
    ...
    out_file.write(...)

А что если я захочу написать в sys.stdout, если нет file_name?

Обязательно ли мне нужно обернуть все действия в функции и поставить условие раньше?

if file_name is None:
    do_everything(sys.stdout)
else:
    with open(file_name, 'w') as out_file:
        do_everything(out_file)

Ответы [ 5 ]

6 голосов
/ 23 марта 2012
from contextlib import contextmanager
@contextmanager
def file_or_stdout(file_name):
    if file_name is None:
        yield sys.stdout
    else:
        with open(file_name, 'w') as out_file:
            yield out_file

Тогда вы можете сделать

with file_or_stdout(file_name) as wfile:
    do_stuff_writing_to(wfile)
3 голосов
/ 23 марта 2012

Как вы обрабатываете аргументы командной строки?Если вы используете argparse, вы можете использовать type и default для add_argument.Например, попробуйте что-то вроде следующего:

import sys
import argparse

def main(argv=None):

    if argv is None:
        argv=sys.argv[1:]

    parser = argparse.ArgumentParser()

    parser.add_argument('infile', nargs='?',
        type=argparse.FileType('w'),
        default=sys.stdin)

    args = parser.parse_args(argv)

    print args.infile

    return 0

if __name__=="__main__":
    sys.exit(main(sys.argv[1:]))

Если в качестве аргумента указано имя файла, скрипт argparse автоматически откроет и закроет этот файл, а args.infile будет дескриптором этого файла.В противном случае args.infile будет просто sys.stdin.

2 голосов
/ 23 марта 2012

Вы можете написать свой собственный менеджер контекста.Я опубликую пример кода позже, если никто не сделает

0 голосов
/ 23 марта 2012

Использование конструкции with ... as полезно для автоматического закрытия файла.Это означает, что использование его с sys.stdout, как я думаю, вы знаете, приведет к краху вашей программы, потому что она попытается закрыть системный вывод!

Это означает что-то вроде with open(name, 'w') if name else sys.stdout as:это не сработало бы.

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

Главное, что нужно уточнить, - это когда вам нужно открыть (и, что более важно, закрыть) обработчик файла для file_name, когда существует имя файла.

Лично я бы просто отбросил with .. as и взялпозаботьтесь об открытии файла - и, что более важно, закройте его!- где-нибудь еще.Пробег для этого может варьироваться в зависимости от того, как работает ваше программное обеспечение.

Это означает, что вы можете просто:

out_file = open(file_name, 'w') if file_name else sys.stdout

и работать с out_file во всей вашей программе.

КогдаВы закрываете, не забудьте проверить, является ли это файл или нет:)

А вы не задумывались о том, чтобы просто использовать модуль logging?Это позволяет легко добавлять разные обработчики, печатать в файл, печатать на стандартный вывод ...

0 голосов
/ 23 марта 2012
if file_name is None:
    fd = sys.stdout
else:
    fd = open(file_name, 'w')

# write to fd

if fd != sys.stdout:
    fd.close();
...