Парсинг XML-файл, содержащий некоторые события


Я новичок и написал свой первый модуль питона, который анализирует XML-файл, содержащий некоторые события и выводит их на стандартный вывод в формате JSON. Я был бы признателен некоторые отзывы о дизайн, верстка, код, лучшие практики, что можно оптимизировать и так далее.

from __future__ import with_statement

import json
import xml.etree.ElementTree as etree


def _sanitize_string(string):
    """docstring for _clean_string"""
    string = string.replace('\n', '').split()
    return ' '.join(string)


class Event(object):
    """docstring for Event"""
    def __init__(self, date, event, organizer, time, venue):
        self.date = date
        self.event = event
        self.organizer = organizer
        self.time = time
        self.venue = venue

    def provide_data(self):
        """docstring for provide_data"""
        data = {}
        data['date'] = self.date
        data['event'] = self.event
        data['organizer'] = self.organizer
        data['time'] = self.time
        data['venue'] = self.venue
        return data


class EventCollection(list):
    """docstring for EventCollection"""
    def __init__(self):
        super(EventCollection, self).__init__([])

    def as_json(self):
        """docstring for as_json"""
        print json.dumps([event.provide_data() for event in self],
                         sort_keys=True, indent=2)


def read_file(event_collection, filename='events.xml'):
    """docstring for read_file"""
    try:
        with open(filename) as f:
            tree = etree.parse(f)
        for row in tree.findall('.//row'):
            # event = [_sanitize_string(node.text) for node in row]
            # if event[0] and event[0][0].isdigit():
            #     print event
            tmpl = [_sanitize_string(node.text) for node in row]
            if tmpl[0] and tmpl[0][0].isdigit():
                event = Event(tmpl.pop(0), tmpl.pop(0), tmpl.pop(0),
                              tmpl.pop(0), tmpl.pop(0))
            event_collection.append(event)
    except IOError as ioerr:
        print "File Error: %s" % str(ioerr)


def main():
    """docstring for main"""
    event_collection = EventCollection()

    read_file(event_collection)

    event_collection.as_json()
    # event_collection.as_csv()


if __name__ == '__main__':
    main()


Комментарии
1 ответ

from __future__ import with_statement

import json
import xml.etree.ElementTree as etree

def _sanitize_string(string):
"""docstring for _clean_string"""

Комментарии должны содержать описание функции, а не старые названия функции.

    string = string.replace('\n', '').split()

Вы действительно хотите, чтобы "зеленые\ngrass', чтобы прийти через Как Гринграсс'?

   return ' '.join(string)

class Event(object):
"""docstring for Event"""
def __init__(self, date, event, organizer, time, venue):
self.date = date
self.event = event
self.organizer = organizer
self.time = time
self.venue = venue

def provide_data(self):
"""docstring for provide_data"""
data = {}
data['date'] = self.date
data['event'] = self.event
data['organizer'] = self.organizer
data['time'] = self.time
data['venue'] = self.venue
return data

Класс как она стоит на самом деле не делать ничего. Если это все никогда не собирался этого делать, просто вместо того, чтобы использовать словарь.

class EventCollection(list):
"""docstring for EventCollection"""

def __init__(self):
super(EventCollection, self).__init__([])

Прохождение [] - пустое, потому что пустой аргумент конструктора будет иметь тот же эффект, не создавая временный список. Нет необходимости переопределять здесь Конструктор. Поведение по умолчанию будет строить список просто отлично.

    def as_json(self):
"""docstring for as_json"""
print json.dumps([event.provide_data() for event in self],
sort_keys=True, indent=2)

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

def read_file(event_collection, filename='events.xml'):
"""docstring for read_file"""
try:
with open(filename) as f:
tree = etree.parse(f)
for row in tree.findall('.//row'):
# event = [_sanitize_string(node.text) for node in row]
# if event[0] and event[0][0].isdigit():
# print event

Не держать мертвым кода в комментариях, удалите его.

            tmpl = [_sanitize_string(node.text) for node in row]

Я не могу угадать, что tmpl является значит. Это XML-файле, эти узлы имеют Теги, что вы должны быть проверка на корректность?

            if tmpl[0] and tmpl[0][0].isdigit():

Я не знаю, что этот тест делает. Вероятно, она должна прокомментировал объяснить signficance того, что первый символ является цифрой.

                event = Event(tmpl.pop(0), tmpl.pop(0), tmpl.pop(0),
tmpl.pop(0), tmpl.pop(0))

Использование:
дата, событие, время, организатор, место проведения = КГБУ
событие = событие(дата, событие, время, организатор, место проведения)

Это делает это легче увидеть, что происходит

            event_collection.append(event)
except IOError as ioerr:
print "File Error: %s" % str(ioerr)

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

def main():
"""docstring for main"""
event_collection = EventCollection()

read_file(event_collection)

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

    event_collection.as_json()
# event_collection.as_csv()

if __name__ == '__main__':
main()

** Редактировать **

Способы обработки исключений:


  1. Нет. Просто взять попробовать и за исключением. Если что-то пойдет не так, ваша программа будет умирать с трассировки стека. Не очень профессионально, но в некоторых случаях это просто отлично

  2. Используйте sys.выход()

    попробуйте:
    do_stuff()
    кроме IOError:
    печать "пошло не так"
    Сыс.программа выхода() # Выход здесь


  3. Используйте свой собственный класс исключений (мой предпочтительный метод)

Код:

class UserError(Exception):
"""
This error is thrown when it the user's fault
Or at least the user should see the error
"""

# later
try:
do_stuff()
except IOError as error:
raise UserError(error)

# later
def main():
try:
do_program()
except UserError as error:
print error

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

Два других вопроса:


  1. Вы действительно должны напечатать >> sys файла.поток stderr, "ошибка сообщения" , так что ваши ошибки идут в стандартный поток ошибок, а не стандартный из

  2. Вы должны также закончиться вызовом sys файла.выход(некоторое ненулевое число) , когда ошибка происходит, чтобы указать отказ.

3
ответ дан 10 июля 2011 в 12:07 Источник Поделиться