Найти - Пользователи
Полная версия: Одновременный вывод в консоль и в файл
Начало » Python для новичков » Одновременный вывод в консоль и в файл
1 2
admiral
Здравствуйте.
Хочу сделать, что бы при работе программы она выводила информацию не только в консоль, но и в файл (что-то типа логирования). Как это лучше всего реализовать?
Сначала хотел использовать logging. Но у него какая-то загвоздка: при запуске из PyScripter - он вообще ничего не выводит. А при запуске в консоли - все нормально отображает. Да и не сильно-то мне нужны все те навороты, что там имеются.
В общем хочу я просто заменить все вызовы print на свою функцию printlog.
def printlog (a):
    print (a)
    добавление_строки_в_файл(a) 
Только не нравиться мне то, что что бы добавить строку в файл - файл нужно вначале открыть, потом добавить строку, потом закрыть его. Можно ли сделать так, что бы файл открывался один раз, а функция только добавляла строку в уже открытый файл?
Razor
def printlog (a):
    print (a)
    with open('log.txt', 'a') as logfile:
        logfile.write(a, '\n')
admiral
Спасибо. Помогло.
только надо было написать
logfile.write(a + '\n')
bw
Я бы не использовал `write` напрямую и не закрывал бы каждый раз лог-файл:
logfile = None
logpath = 'log.txt'
def printlog(*args):
    global logfile
    print(*args)
    if logfile is None:
        logfile = open(logpath, 'a')
    print(*args, file=logfile)
    #logfile.flush()

p.s. `logging` это всё же стандартный инструмент, а `print` сильно отдаёт кустарщиной, оно годится конечно, но для небольших (одноразовых) скриптов; другими словами, семантика у `print` и `logging` разная, не стоит вести протоколирование работы приложения с помощью `print`, как не стоит разрабатывать веб-приложения на Django лезть в `sys.path` вместо использования нормальной (устоявшейся) системы установки пакетов.

..bw
doza_and
Используйте logging, наплюйте на pyscripter. У pyscripter проблема с тем, что кажется консолью. На самом деле это не консоль а неизвестно что. https://code.google.com/p/pyscripter/issues/detail?id=685

Есть утилита tie http://www.skrenta.com/rt/man/tie.1.html Она предназначена для решения вашей задачи. Для windows можно поставить cygwin (всего пару гигабайт) и вы получите доступ почти ко всем unix утилитам. :)

Успешного освоения питона.
admiral
Сделал такой код:
def printlog(*args):
    global logfile
    print (time.strftime("%H:%M:%S") + " ", *args)
    if logfile is None:
        logfile = open(LOGFILE, 'a')
    print(time.strftime("%H:%M:%S") + " ", *args, file=logfile)

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

еще вопрос, нельзя ли logfile = open(LOGFILE, ‘a’) вынести из функции? все равно же logfile является глобальной переменной.
Razor
admiral
нельзя ли logfile = open(LOGFILE, ‘a’) вынести из функции
Можно. logfile будет глобальной переменной снаружи и функция ее увидит.

И не забудьте закрывать файл. with сам закрывает файл, а так вам придется писать каждый раз logfile.close()
bw
> а ничего туда не пишется
Всё туда пишется, откройте для себя буферизацию. В данном случае как минимум системный присутствует, есть ли у Python – не знаю. Собственно я как бы намекнул одной закомментированой строкой, что чего, а нужно ли, это уже не ко мне.
Или после завершения приложения файл всё ещё пустой? В это трудно поверить.

> вам придется писать каждый раз logfile.close()
И зачем придётся это писать каждый раз? И вы забыли сказать, что в таком случае (если использовать мой код), так же каждый раз придётся писать logfile = None и каждый раз будет срабатывать if logfile is None: … и каждый раз будет открываться один и тот же файл. И зачем я так странно сделал? А, ну да, что бы на 10000 лог-сообщений 10000 раз открывать и 10000 раз закрывать файл.
Зачем дурацкие советы даёте?

За `close` в подавляющем большинстве случаев переживать не нужно, всё там рано или поздно закроется (когда потеряется последняя ссылка на файловый объект). Но вообще про with open(…) знать конечно нужно.

Можно сделать так, если заняться больше нечем:
import atexit
logfile = None
# ...
    if logfile is None:
        logfile = open(...)
        atexit.register(logfile.close)
# ...

p.s. Зачем два раза `strftime`, в чём прикол, что бы одна и та же лог-запись с разным временем на экране и в файле была или просто слишком много ядер на вашем дрофоне?

..bw
admiral
bw
Всё туда пишется, откройте для себя буферизацию. В данном случае как минимум системный присутствует, есть ли у Python – не знаю. Собственно я как бы намекнул одной закомментированой строкой, что чего, а нужно ли, это уже не ко мне.Или после завершения приложения файл всё ещё пустой? В это трудно поверить.
Спасибо. Все заработало.
Вот окончательный вариант:
def printlog(*args):
    """
    Подпрограмма одновременного вывода строки на экран и в файл
    """
    global logfile
    t = time.strftime("%H:%M:%S") + " "
    print (t, *args)
    if logfile is None:
        try:
            logfile = open(LOGFILE, 'a')
        except Exception:
            print (t, "Не могу открыть лог-файл")
    else:
        try:
            #logfile.write(t + str(*args) + '\n')
            print(t, *args, file = logfile)
            logfile.flush()
        except Exception:
            print (t, "Не могу добавить строку в лог-файл")
doza_and
:)
admiral
Вот окончательный вариант:
В это с трудом верится.
Осталось пояснить :
1 Чем этот велосипед лучше модуля logging?
2. Зачем при каждой записи делается проверка?
logfile is None
3. Как
logfile.flush()
повлияет на производительность вашей системы записи логов?
4. Почему вы заловили все Exception и вместо них вывели сообщения в консоль (которой часто у приложения просто нет или ее не видно)?

Извините если обидел.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB