Как правильно передавать ошибки из классов в рендеринг HTML в Python - PullRequest
1 голос
/ 28 февраля 2010

Я выполняю всю проверку формы в классе и хотел бы иметь возможность получать ошибки из класса в визуализированный html. Один из подходов, о котором я думал, - это создать глобальную переменную «c», в которой будут храниться все ошибки, и устанавливать их из класса, так как я все еще хочу, чтобы отдельные методы возвращали false при сбое. Вот пример кода:

class User():

def add(self):

    #Check that e-mail has been completed
    try:
        #Validate e-mail address
        if (isAddressValid(self.email)):
            c.error = 'Invalid e-mail address'
            return 0
    except NameError:
        c.error = 'No e-mail address specified'
        return 0

Есть ли лучший или предпочтительный способ сделать это?

Спасибо.

Ответы [ 3 ]

1 голос
/ 28 февраля 2010

Да, безусловно, и я советую вообще не возвращать коды состояния.

Вообще говоря, существует много литературы против использования кодов состояния и глобальных переменных для хранения деталей для обработки ошибок в среде высокого уровня, такой как Python.
Нед Бэтчелдер написал очень хорошую статью на эту тему ; Я настоятельно рекомендую вам прочитать эту страницу, чтобы получить список причин, по которым обработка исключений обычно считается лучшим методом.

Но, как мы говорим о Python, официальный способ сообщения об исключениях и ошибках - через обработку исключений. Период.
Использование любого другого способа приведёт ваш код в соответствие с общими ожиданиями в отношении кода Python, что означает, что его будет сложнее читать и поддерживать.

1 голос
/ 01 марта 2010

В контексте веб-приложения вы можете просто заполнить tmpl_context.

from pylons import tmpl_context as c
from yourproject.lib.base import BaseController, render

class MyController(BaseController):
    def index(self):
        c.error = 'Invalid e-mail address'
        return render('/mytemplate.mako')

Где 'mytemplate.mako' Содержимое файла:

% if c.error:
    error: ${c.error}
% endif

В общем коде Python вы можете:

Вернуть кортеж

Вы можете вернуть кортеж из своей функции (это не предпочтительный способ):

class Error(Exception):
    pass

def isvalid(something):
    return False, Error("'%s' is invalid" % (something,))

Пример:

ok, err = isvalid(object())
if not ok:
   print err

Поднять исключение

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

def do_stuff(something):
    if not something.isready():
       raise Error("'%s' is not ready to do stuff" % (something,))

Пример:

class C(object):
    def isready(self):
        return False

def run():
    # no error handling here
    do_stuff(C()) 
    # do something else

try: run()
except Error, e:
    print e

Пропуск обратного вызова

def do_stuff(something, onerror=lambda err: None):
    if not something.isready():
       onerror(Error("'%s' is not ready to do stuff" % (something,)))

Пример:

do = lambda: do_stuff(C(), onerror=repeat)
def repeat(err):
    """Repeat until success."""
    print err
    time.sleep(5) 
    do() # possible infinite loop 
do()
1 голос
/ 28 февраля 2010

Мне нравится использовать словарь для хранения ошибок и предупреждений. Тогда я могу либо показать все ошибки в верхней части формы или встроенного. Я также определяю переменные error и warning, чтобы я мог легко разделить их.

class User(object):
    def __init__(self):
        self.messages = {}

    def add(self):
        error = False
        warning = False

        #Check that name has a space
        try:
            if (self.name.find(' ') == -1):
                warning = True
                self.messages['email'] = {'type': 'warning',
                                          'msg': 'Your name has no space.'}
        except NameError:
            error = True
            self.messages['email'] = {'type': 'error',
                                      'msg': 'You have no name.'}

        #Check that e-mail has been completed
        try:
            #Validate e-mail address
            if (isAddressValid(self.email)):
                error = True
                self.messages['email'] = {'type': 'error',
                                          'msg': 'Invalid e-mail address'}
        except NameError:
            error = True
            self.messages['email'] = {'type': 'error',
                                      'msg': 'No e-mail address specified'}

        return error, warning
...