Как я могу разделить Python, регистрирующий вызовы, не комментируя их?

var bombout=0;
var checkArr=[];
var arr=[];
while(arr.length < 8 && bombout<100){
  bombout++;
  var randomNumber=Math.ceil(Math.random()*100);
  if(typeof checkArr[randomNumber] == "undefined"){
    checkArr[randomNumber]=1;
    arr.push(randomNumber);
  }
}​

// untested - hence bombout
28
задан cdleary 13 February 2009 в 23:25
поделиться

8 ответов

Что относительно того, чтобы использовать logging.disable?

я также нашел, что должен был использовать logging.isEnabledFor, если регистрирующееся сообщение является дорогим для создания.

20
ответ дан maccullt 14 October 2019 в 11:36
поделиться

Как несовершенный ярлык, как насчет того, чтобы дразнить logging в определенных модулях с помощью чего-то как MiniMock?

, Например, если my_module.py был:

import logging
class C(object):
    def __init__(self, *args, **kw):
        logging.info("Instantiating")

Вы заменили бы свое использование my_module с:

from minimock import Mock
import my_module
my_module.logging = Mock('logging')
c = my_module.C()

необходимо было бы только сделать это однажды перед начальным импортом модуля.

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

На практике, Вы, вероятно, хотели бы заменить MiniMock чем-то более простым и более быстрым; по крайней мере что-то, что не печатает использование к stdout! Конечно, это не решает проблему модуля импорт logging от модуля B (и следовательно также импорт гранулярности журнала B)...

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

2
ответ дан James Brady 14 October 2019 в 11:36
поделиться

Вы могли попробовать что-то вроде этого:

# Create something that accepts anything
class Fake(object):
    def __getattr__(self, key):
        return self
    def __call__(self, *args, **kwargs):
        return True

# Replace the logging module
import sys
sys.modules["logging"] = Fake()

Это по существу заменяет (или первоначально заполняет), пространство для регистрирующегося модуля с экземпляром Fake, который просто берет в чем-либо. Необходимо выполнить вышеупомянутый код (только однажды!), прежде чем регистрирующийся модуль предпринят, чтобы использоваться где угодно. Вот тест:

import logging

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(levelname)-8s %(message)s',
                    datefmt='%a, %d %b %Y %H:%M:%S',
                    filename='/temp/myapp.log',
                    filemode='w')
logging.debug('A debug message')
logging.info('Some information')
logging.warning('A shot across the bows')

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

1
ответ дан Evan Fosmark 14 October 2019 в 11:36
поделиться

Это - проблема в моем проекте также - вход заканчивается на профилировщике, сообщает довольно последовательно.

я использовал _ast модуль прежде в ветвлении PyFlakes ( http://github.com/kevinw/pyflakes )..., и определенно возможно сделать то, что Вы предлагаете в своем вопросе - осмотреть и ввести защиту перед вызовами к регистрирующимся методам (с Вашим подтвержденным протестом, что необходимо было бы сделать некоторую проверку типа выполнения). См. http://pyside.blogspot.com/2008/03/ast-compilation-from-python.html для простого примера.

Редактирование: я просто заметил MetaPython на моем канале planetpython.org - вариант использования в качестве примера удаляет операторы журнала во время импорта.

, Возможно, лучшее решение состояло бы в том, чтобы кто-то повторно реализовал вход как модуль C, но я не был бы первым для схватывания такого... возможность: p

1
ответ дан keelo 14 October 2019 в 11:36
поделиться

Я использовал бы некоторого необычного декоратора входа или набор их:

def doLogging(logTreshold):
    def logFunction(aFunc):
        def innerFunc(*args, **kwargs):
            if LOGLEVEL >= logTreshold:
                print ">>Called %s at %s"%(aFunc.__name__, time.strftime("%H:%M:%S"))
                print ">>Parameters: ", args, kwargs if kwargs else "" 
            try:
                return aFunc(*args, **kwargs)
            finally:
                print ">>%s took %s"%(aFunc.__name__, time.strftime("%H:%M:%S"))
        return innerFunc
    return logFunction

Все, в чем Вы нуждаетесь, должно объявить константу LOGLEVEL в каждом модуле (или просто глобально и просто импортировать его во всех модулях), и затем можно использовать его как это:

@doLogging(2.5)
def myPreciousFunction(one, two, three=4):
    print "I'm doing some fancy computations :-)"
    return

И если LOGLEVEL - не менее чем 2,5, Вы будете произведены как это:

>>Called myPreciousFunction at 18:49:13
>>Parameters:  (1, 2) 
I'm doing some fancy computations :-)
>>myPreciousFunction took 18:49:13

, Как Вы видите, некоторая работа необходима для лучшей обработки kwargs, таким образом, значения по умолчанию будут распечатаны, если они будут присутствовать, но это - другой вопрос.

необходимо, вероятно, использовать приблизительно [1 113] logger модуль вместо сырых данных print операторы, но я хотел сфокусироваться на идее декоратора и постараться не делать код слишком долго.

Так или иначе - с таким декоратором Вы получаете вход функционального уровня, произвольно много уровней журнала, простоты приложения к новой функции, и отключить вход Вас только должно установить LOGLEVEL. И можно определить различные выходные потоки/файлы для каждой функции, если Вы желаете. Можно записать doLogging как:

 def doLogging(logThreshold, outStream=sys.stdout):
      .....
      print >>outStream, ">>Called %s at %s" etc.

И используют файлы журнала, определенные на основе на функцию.

1
ответ дан Abgan 14 October 2019 в 11:36
поделиться

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

assert logging.warn('disable me with the -O option') is None

(Я предполагаю, что предупреждают, всегда не возвращает ни один.. в противном случае Вы получите AssertionError

Но действительно это - просто забавный способ сделать это:

if __debug__: logging.warn('disable me with the -O option')

Когда Вы запустите скрипт с той строкой в нем с-O опцией, строка будет удалена из оптимизированного кода .pyo. Если, вместо этого, у Вас была своя собственная переменная, как в следующем, у Вас будет условное выражение, которое всегда выполняется (независимо от того, что оценивает переменную), хотя условное выражение должно выполниться более быстрый, чем вызов функции:

my_debug = True
...
if my_debug: logging.warn('disable me by setting my_debug = False')

таким образом, если мое понимание отладки корректно, это походит на хороший способ избавиться от ненужных вызовов входа. Обратная сторона - то, что это также отключает весь Ваш, утверждает, таким образом, это - проблема при необходимости в утверждении.

5
ответ дан the_drow 28 November 2019 в 03:37
поделиться

Мне нравится решение 'if __debug_', за исключением того, что помещать его перед каждым вызовом немного отвлекает и некрасиво. У меня была такая же проблема, и я решил ее, написав скрипт, который автоматически анализирует ваши исходные файлы и заменяет операторы журналирования операторами pass (и закомментировал копии операторов журналирования). Он также может отменить это преобразование.

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

Вы можете найти сценарий здесь: http://dound.com/2010/02/python-logging-performance/

0
ответ дан 28 November 2019 в 03:37
поделиться

:-) Раньше мы называли это препроцессором, и хотя препроцессор языка Си обладал некоторыми из этих возможностей, "королем холма" был препроцессор для IBM mainframe PL/I. Он обеспечивал широкую поддержку языка в препроцессоре (полные присваивания, условия, циклы и т.д.), и можно было писать "программы, которые писали программы", используя только PL/I PP.

Я написал много приложений с полноценной сложной трассировкой программ и данных (в то время у нас не было достойного отладчика для внутреннего процесса) для использования в разработке и тестировании, которые затем, при компиляции с соответствующим "флагом времени выполнения", просто удаляли весь код трассировки без какого-либо влияния на производительность.

Я думаю, что идея декораторов хороша. Вы можете написать декоратор для обертывания функций, которые нуждаются в протоколировании. Затем, для распространения во время выполнения, декоратор превращается в "no-op", что устраняет отладочные утверждения.

Jon R

1
ответ дан 28 November 2019 в 03:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: