2013-03-09 2 views
6

Короткая версияУсловный оператор __debug__ не выполняется, хотя __debug__ это правда

У меня есть часть кода, я отладки, который проверяет значение __debug__ и выполняет код, если это правда.

if __debug__: 
    <stuff happens> 

Проблема заключается в том, что «материал» никогда не бывает, даже если __debug__ появляется, чтобы быть правдой.

Long Version/Детали

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

try: 
    myfile = os.open("test.txt", os.O_RDWR|os.O_CREAT|os.O_APPEND) 
    # work + some print statements to check the value of __DEBUG__ 
finally: 
    os.close(myfile) 

Кусок кода я больше всего смущают выглядит следующим образом:

os.write(myfile, "LINE %s | LDAP FUNCTION __DEBUG__: %s \n" %(sys._getframe(0).f_lineno, __debug__)) 
os.write(myfile, "LINE %s | LDAP FUNCTION __DEBUG__: %s \n" %(sys._getframe(0).f_lineno, type(__debug__))) 
os.write(myfile, "LINE %s | LDAP FUNCTION __DEBUG__: %s \n" %(sys._getframe(0).f_lineno, bool(__debug__))) 
if __debug__: 
    os.write(myfile, "LINE %s | LDAP FUNCTION __DEBUG__: %s \n" %(sys._getframe(0).f_lineno, __debug__)) 
if bool(__debug__): 
    os.write(myfile, "LINE %s | LDAP FUNCTION __DEBUG__: %s \n" %(sys._getframe(0).f_lineno, __debug__)) 
if True: 
    os.write(myfile, "LINE %s | LDAP FUNCTION __DEBUG__: %s \n" %(sys._getframe(0).f_lineno, __debug__)) 
if __debug__: 
    os.write(myfile, "LINE %s | LDAP FUNCTION __DEBUG__: %s \n" %(sys._getframe(0).f_lineno, __debug__)) 

И выходной файл выглядит следующим образом :

LINE 82 | LDAP FUNCTION __DEBUG__: True 
LINE 83 | LDAP FUNCTION __DEBUG__: <type 'bool'> 
LINE 84 | LDAP FUNCTION __DEBUG__: True 
LINE 88 | LDAP FUNCTION __DEBUG__: True 
LINE 90 | LDAP FUNCTION __DEBUG__: True 

первое 3 заявление (строки 82-84) является каждым способом, которым я мог думать о проверке, если __debug__ является «truthy», и все 3 означают, что __debug__ - правда. Аналогично, кастинг __debug__ как булево, а затем оценка if (строка 88) также работает так же, как ожидалось. Строка 90 - глупая проверка здравомыслия.

Есть ли что-то, что мне не хватает на пути __debug__ работ, которые могут быть причиной этого?

Примечание: Я нашел это в то время я работал за ошибки я получаю в функции _ldap_function_call в python-ldap модуле. Я получаю эту ошибку только при использовании IIS - все отлично работает с сервером разработки Django.

+1

Какая версия Python это? В версиях 2.7 и 3.x присвоение '__debug__' является' SyntaxError'; в более ранних версиях 2.x '__debug__' не был волшебной константой, но в версии 2.6 и несколькими версиями до этого (не уверен, сколько), это волшебная константа, но вы можете переписать это имя на что-то еще, что приводит к странности. – abarnert

+0

Возможно, это вызвано чем-то странным: я подозреваю файлы .pyc/.pyo. Удаляет ли какой-либо файл .pyc/.pyo, чтобы решить проблему? –

+1

@abarnert: Ах. Но странность все еще возможна: http://bpaste.net/show/82378/. turtlemonvh: либо ваш код mangle '__debug__' таким образом, либо, скорее всего, код контекста (python-ldap?). –

ответ

3

Если вы перепечатываете __debug__, это может привести к таким симптомам.

Это потому, что __debug__ несколько волшебный. Во время компиляции модуля тот же код, который обрабатывает литералы, также обрабатывает магические константы ..., None, True, False и __debug__. (См, например, expr_constant.)

Если запустить dis на свой код, чтобы разгружать байты-код, вы увидите, что if __debug__: заявление либо полностью удалены, либо использовать LOAD_CONST для загрузки во время компиляции debug константы, в то время как в сообщениях if bool(__debug__): используется LOAD_GLOBAL для загрузки значения __debug__.

Конечно, они гарантированно будут такими же ... если вы не повторите попытку __debug__. Где-то около 2,3, было запрещено писать __debug__ = False. В версиях 2.7 и 3.0 стало запрещено связывать атрибут с именем __debug__, что означает, что вы больше не можете делать такие вещи, как sys.modules[__name__].__debug__ = False. Но вы все равно можете сделать, например, globals()['__debug__'] = False.

И в любом случае, вы получите тот же эффект:

if __debug__: 
    print "debug" 
if bool(__debug__): 
    print "bool" 

import sys 
sys.modules[__name__].__debug__ = False 

if __debug__: 
    print "debug2" 
if bool(__debug__): 
    print "bool2" 

Это печатает:

debug 
bool 
debug2 

А также для кода, который устанавливает его Правда при запуске с python -O.

+1

В 2.6-3.3 любое богатое сравнение с '__debug__' также запускает' LOAD_NAME' (в модуле/классе) или 'LOAD_GLOBAL' (в функции). Если вы работаете без '-O', то набор для' if __debug__' встроен; в противном случае он опускается. Я не видел «LOAD_CONST», используемый для проверки состояния отладки в любом из моих тестов. Какая версия Python компилирует ее в 'co_consts'? – eryksun

+0

@abarnert Этот звук похож на солидную логику для меня. Я не нашел места в ldap-связанных модулях, где '__debug__' был изменен, но я думаю, что [библиотека PyISAPIe] (http://sourceforge.net/apps/trac/pyisapie), которую я использую для запуска django в IIS может быть частью проблемы. – turtlemonvh

+0

@abarnet Связанный вопрос - из-за этапа предварительной обработки 'if __debug__ и True:'! = 'If __debug __:', правильно? Первоначально я обнаружил эту аномалию, разбив '' '' 'и' если бы заявления в несколько утверждений, и заметил, что это изменило, какие ошибки я получал. Я предполагаю, что это одни и те же явления. – turtlemonvh

Смежные вопросы