Куда что-то печатает, когда приложение не запущено с терминала?

Итак, у меня есть приложение Python, которое объединяется в .app с использованием py2app. У меня есть несколько отладочных операторов печати, которые обычно печатаются на стандартный вывод, если я запускаю код в терминале. Если я просто открою связанное .app, очевидно, я не увижу ничего из этого вывода. Что-то из этого на самом деле печатается где-то, хотя я этого не вижу?


person vik    schedule 09.07.2013    source источник
comment
Вероятно, для начала вам следует использовать модуль Python logging, но пробовали ли вы искать в Console.app?   -  person Wooble    schedule 09.07.2013
comment
да, я думал, что он может быть там, но я не видел его там. Отображает ли модуль ведения журнала в console.app?   -  person vik    schedule 09.07.2013


Ответы (3)


Он выходит на стандартный вывод (то есть в командную строку, если вы открываете его в командной строке, или, например, в журнал, если вы запускаете его с заданиями cron).

Для более продвинутого и гибкого использования попробуйте использовать встроенную поддержку ведения журнала (logging модуль). . Он позволяет направлять сообщения на консоль, в файл, поток (например, внешний сервер регистрации), syslog процесс, электронную почту и т. д., а также фильтровать на основе уровня сообщения журнала. Операторы отладки (операторы регистрации) могут быть помещены в производственный код, но настроены так, чтобы не вызывать никаких журналов, кроме ошибок. Очень полезно и значительно упрощает регистрацию.

person Tadeck    schedule 09.07.2013
comment
хорошо, это, кажется, больше из того, что мне нужно. Можно ли использовать модуль ведения журнала для печати данных в стандартный вывод, а также в журнал, таким образом, если я запущу что-то в терминале, я просто увижу вывод в терминале? - person vik; 09.07.2013
comment
@vik: Да, для любого из регистраторов может быть несколько обработчиков. Кроме того, вы можете создавать довольно сложные структуры журналирования (иерархические регистраторы, с или без распространения для каждого из них, различные обработчики, фильтры и средства форматирования). Ведение журнала Python на самом деле было решением, которое стало базой для некоторых других, более новых решений (таких как Monolog от Symfony). - person Tadeck; 09.07.2013

Куда перенаправляются потоки stdout и stderr, зависит от того, как вы запускаете приложение и в какой версии OSX вы находитесь.

Когда вы запускаете приложение из терминала ("MyApp.app/Contents/MacOS/MyApp"), вывод заканчивается в окне терминала.

Когда вы запускаете приложение двойным щелчком или с помощью команды open(1), вывод заканчивается в Console.app при использовании OSX до 10.8 и отбрасывается в OSX 10.8.

У меня есть патч, который перенаправляет вывод в журналы, которые Console.app читает даже для OSX 10.8, но на данный момент его нет в выпущенной версии.

P.S. Я сопровождаю py2app.

person Ronald Oussoren    schedule 10.07.2013

Я думаю, вы можете взглянуть на модуль с именем logging.

Затем вы можете использовать этот модуль для записи собственных журналов в отдельный файл, например, так я это делаю:

import logging

# Create a log file for the future debug
LOG_FILE_NAME = 'my-script.log'
log_path = path = os.path.join(os.path.expanduser('~'), '/mnt/logs/') 
if not os.path.exists(log_path):
    os.makedirs(log_path)
logger = logging.getLogger('my-script')
logger.setLevel(logging.DEBUG)
file_handler = logging.FileHandler(log_path+LOG_FILE_NAME)
file_handler.setLevel(logging.DEBUG)
file_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s -%(message)s')
file_handler.setFormatter(file_formatter)
logger.addHandler(file_handler)

class Foo()

    def log(self, msg, level=None):
        print "LOG %s" % msg
        if level is not None:
            if level == 'INFO':
                logger.info(msg)
            elif level == 'WARNING':
                logger.warn(msg)
            elif level == 'ERROR':
                logger.error(msg)
            elif level == 'CRITICAL':
                logger.critical(msg)
        else:
            logger.debug(msg) # DEBUG

    self.log('Some text here', 'DEBUG') # I use self.log instead of print
person Vor    schedule 09.07.2013
comment
Две вещи: 1) Почему вы настаиваете на переопределении стандартного поведения ведения журнала? Похоже, такой подход не дает вам никаких преимуществ? 2) Этот подход заставляет перезаписывать любую конфигурацию ведения журнала, в то время как лучший подход состоит в том, чтобы просто предоставить стандартный обработчик (обработчик null/no-op) и обрабатывать конфигурацию ведения журнала в другом месте (в качестве примера взгляните на конфигурацию ведения журнала Django). - person Tadeck; 09.07.2013
comment
Таким образом, это будет печатать сообщение на стандартный вывод, а также регистрировать его? - person vik; 09.07.2013
comment
Да, он распечатает его, если вы запустите его в терминале, а также запишите их в файл журнала. - person Vor; 09.07.2013
comment
Не могли бы вы изменить мой ответ, чтобы показать, что вы имеете в виду на give standard handler - person Vor; 09.07.2013
comment
Я думаю, что это должно быть log_path = os.path.join(os.path.expanduser('~'), 'mnt/logs/'), потому что если вы используете '/mnt/logs/', результат будет именно таким, поскольку он имеет ведущую косую черту. - person martineau; 09.07.2013
comment
@Vor: Вот информация о том, как это сделать для NullHandler, и объяснение, почему его не следует настраивать так, как вы предложили: docs.python.org/2/howto/ - person Tadeck; 09.07.2013