Уведомления

Группа в Telegram: @pythonsu

#1 Янв. 3, 2014 17:54:09

admiral
Зарегистрирован: 2013-12-23
Сообщения: 33
Репутация: +  0  -
Профиль   Отправить e-mail  

Одновременный вывод в консоль и в файл

Здравствуйте.
Хочу сделать, что бы при работе программы она выводила информацию не только в консоль, но и в файл (что-то типа логирования). Как это лучше всего реализовать?
Сначала хотел использовать logging. Но у него какая-то загвоздка: при запуске из PyScripter - он вообще ничего не выводит. А при запуске в консоли - все нормально отображает. Да и не сильно-то мне нужны все те навороты, что там имеются.
В общем хочу я просто заменить все вызовы print на свою функцию printlog.

def printlog (a):
    print (a)
    добавление_строки_в_файл(a) 
Только не нравиться мне то, что что бы добавить строку в файл - файл нужно вначале открыть, потом добавить строку, потом закрыть его. Можно ли сделать так, что бы файл открывался один раз, а функция только добавляла строку в уже открытый файл?



Win7 + Python3.3 + PyScripter

Офлайн

#2 Янв. 3, 2014 18:02:35

Razor
Зарегистрирован: 2012-09-11
Сообщения: 127
Репутация: +  2  -
Профиль   Отправить e-mail  

Одновременный вывод в консоль и в файл

def printlog (a):
    print (a)
    with open('log.txt', 'a') as logfile:
        logfile.write(a, '\n')

Офлайн

#3 Янв. 3, 2014 18:32:27

admiral
Зарегистрирован: 2013-12-23
Сообщения: 33
Репутация: +  0  -
Профиль   Отправить e-mail  

Одновременный вывод в консоль и в файл

Спасибо. Помогло.
только надо было написать

logfile.write(a + '\n')



Win7 + Python3.3 + PyScripter

Офлайн

#4 Янв. 3, 2014 19:25:22

bw
От:
Зарегистрирован: 2007-09-26
Сообщения: 938
Репутация: +  20  -
Профиль   Адрес электронной почты  

Одновременный вывод в консоль и в файл

Я бы не использовал `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



Отредактировано bw (Янв. 3, 2014 21:09:41)

Офлайн

#5 Янв. 3, 2014 21:39:01

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Одновременный вывод в консоль и в файл

Используйте 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 утилитам. :)

Успешного освоения питона.



Офлайн

#6 Янв. 4, 2014 12:39:16

admiral
Зарегистрирован: 2013-12-23
Сообщения: 33
Репутация: +  0  -
Профиль   Отправить e-mail  

Одновременный вывод в консоль и в файл

Сделал такой код:

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 является глобальной переменной.



Win7 + Python3.3 + PyScripter

Отредактировано admiral (Янв. 4, 2014 12:43:12)

Офлайн

#7 Янв. 4, 2014 14:08:40

Razor
Зарегистрирован: 2012-09-11
Сообщения: 127
Репутация: +  2  -
Профиль   Отправить e-mail  

Одновременный вывод в консоль и в файл

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

И не забудьте закрывать файл. with сам закрывает файл, а так вам придется писать каждый раз logfile.close()

Отредактировано Razor (Янв. 4, 2014 14:32:58)

Офлайн

#8 Янв. 4, 2014 15:13:37

bw
От:
Зарегистрирован: 2007-09-26
Сообщения: 938
Репутация: +  20  -
Профиль   Адрес электронной почты  

Одновременный вывод в консоль и в файл

> а ничего туда не пишется
Всё туда пишется, откройте для себя буферизацию. В данном случае как минимум системный присутствует, есть ли у 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



Отредактировано bw (Янв. 4, 2014 15:32:10)

Офлайн

#9 Янв. 5, 2014 09:35:14

admiral
Зарегистрирован: 2013-12-23
Сообщения: 33
Репутация: +  0  -
Профиль   Отправить e-mail  

Одновременный вывод в консоль и в файл

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, "Не могу добавить строку в лог-файл")



Win7 + Python3.3 + PyScripter

Офлайн

#10 Янв. 5, 2014 10:17:12

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Одновременный вывод в консоль и в файл

:)

admiral
Вот окончательный вариант:
В это с трудом верится.
Осталось пояснить :
1 Чем этот велосипед лучше модуля logging?
2. Зачем при каждой записи делается проверка?
logfile is None
3. Как
logfile.flush()
повлияет на производительность вашей системы записи логов?
4. Почему вы заловили все Exception и вместо них вывели сообщения в консоль (которой часто у приложения просто нет или ее не видно)?

Извините если обидел.



Отредактировано doza_and (Янв. 5, 2014 10:24:50)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version