HOW-TO: Программа на Python, Часть 10 Сравнение версий

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
fullcircle:36:python_ч_10 [2010/08/07 21:08]
fullcircle:36:python_ч_10 [2011/02/20 16:27] (текущий)
Строка 3: Строка 3:
 //​Автор — Грэг Валтерс (Greg Walters)// //​Автор — Грэг Валтерс (Greg Walters)//
 </​style>​ </​style>​
 +
  
   - [[..:​27:​python_ч_1|Программа на Python — часть 1]]   - [[..:​27:​python_ч_1|Программа на Python — часть 1]]
Строка 15: Строка 16:
   - [[..:​36:​python_ч_10|Программа на Python — часть 10]]   - [[..:​36:​python_ч_10|Программа на Python — часть 10]]
   - [[..:​37:​python_ч_11|Программа на Python — часть 11]]   - [[..:​37:​python_ч_11|Программа на Python — часть 11]]
 +  - [[..:​38:​python_ч_12|Программа на Python — часть 12]]
 +  - [[..:​39:​python_ч_13|Программа на Python — часть 13]]
 +  - [[..:​40:​python_ч_14|Программа на Python — часть 14]]
  
 Возможно,​ вы слышали об XML, однако можете и не знать, что это такое. В этом месяце нашу лекцию мы посвятим XML. Цели лекции:​ Возможно,​ вы слышали об XML, однако можете и не знать, что это такое. В этом месяце нашу лекцию мы посвятим XML. Цели лекции:​
  
-• познакомить вас с тем, что такое XML; +  * познакомить вас с тем, что такое XML; 
-• показать,​ как читать и записывать XML-файлы в ваших приложениях;​ +  ​* ​показать,​ как читать и записывать XML-файлы в ваших приложениях;​ 
-• подготовить к серьёзному проекту с использованием XML в следующий раз.+  ​* ​подготовить к серьёзному проекту с использованием XML в следующий раз.
  
 Итак, давайте поговорим об XML. XML означает «EXtensible Markup Language» («Расширяемый язык разметки»). Он достаточно похож на HTML. Формат разработан как способ хранения и эффективной передачи данных через интернет или другим образом. XML – это по существу текстовой файл, отформатированный с использованием ваших собственных тэгов и имеющий хорошие средства самодокументирования. Являясь текстом,​ он может быть сжат для более быстрой и легкой передачи данных. В отличие от HTML, XML сам по себе действий не производит и не связан с визуальным представлением данных. Как я отмечал,​ XML не требует набора стандартных тэгов: вы можете создавать свои собственные. Итак, давайте поговорим об XML. XML означает «EXtensible Markup Language» («Расширяемый язык разметки»). Он достаточно похож на HTML. Формат разработан как способ хранения и эффективной передачи данных через интернет или другим образом. XML – это по существу текстовой файл, отформатированный с использованием ваших собственных тэгов и имеющий хорошие средства самодокументирования. Являясь текстом,​ он может быть сжат для более быстрой и легкой передачи данных. В отличие от HTML, XML сам по себе действий не производит и не связан с визуальным представлением данных. Как я отмечал,​ XML не требует набора стандартных тэгов: вы можете создавать свои собственные.
  
 Давайте взглянем на типичный пример XML-файла. Давайте взглянем на типичный пример XML-файла.
 +<​code>​
 <​root>​ <​root>​
  <​node1>​ Данные… </​node1>​  <​node1>​ Данные… </​node1>​
Строка 33: Строка 37:
  </​node3>​  </​node3>​
 </​root>​ </​root>​
 +</​code>​
 Первое,​ что обращает на себя внимание,​ – это отступы. На самом деле они просто облегчают восприятие человеком. XML-файл будет рабочим,​ даже если он выглядит так: Первое,​ что обращает на себя внимание,​ – это отступы. На самом деле они просто облегчают восприятие человеком. XML-файл будет рабочим,​ даже если он выглядит так:
  
 <​root><​node1>​ Данные… </​node1><​node2 attribute=«something»>​ Данные Узла 2 </​node2><​node3><​node3sub1>​ещё данные</​node3sub1></​node3></​root>​ <​root><​node1>​ Данные… </​node1><​node2 attribute=«something»>​ Данные Узла 2 </​node2><​node3><​node3sub1>​ещё данные</​node3sub1></​node3></​root>​
  
-Тэги внутри угловых скобок «< >» отвечают некоторым правилам. Они должны состоять из одного слова. Каждому открывающему тэгу (например,​ <​root>​) должен соответствовать закрывающий,​ начинающийся с «/». Кроме того, тэги чувствительны к регистру:​ <​node>,​ <​Node>,​ <​NODE>​ и <​NodE>​ – различны,​ и к каждому из них должен быть свой закрывающий тэг. Наименования тэгов могут содержать буквы, цифры и другие символы,​ но не могут начинаться с цифры или знака препинания. Избегайте знаков «-», «.», «:» в именах тэгов, так как некоторые программы могут рассматривать их как команды или свойства объекта. Помимо этого, запятые зарезервированы для некоторых других целей. Тэги также можно называть элементами.+Тэги внутри угловых скобок ​**«< >»** отвечают некоторым правилам. Они должны состоять из одного слова. Каждому открывающему тэгу (например,​ <​root>​) должен соответствовать закрывающий,​ начинающийся с **«/»****Кроме того, тэги чувствительны к регистру:​ <​node>,​ <​Node>,​ <​NODE>​ и <​NodE>​ – различны**, и к каждому из них должен быть свой закрывающий тэг. Наименования тэгов могут содержать буквы, цифры и другие символы,​ но не могут начинаться с цифры или знака препинания. Избегайте знаков «-», «.», «:» в именах тэгов, так как некоторые программы могут рассматривать их как команды или свойства объекта. Помимо этого, запятые зарезервированы для некоторых других целей. Тэги также можно называть элементами.
  
 Каждый XML-файл – это древовидная структура,​ начинающаяся с корня и ответвляющаяся от него. Он ДОЛЖЕН иметь корневой элемент – родитель для всех других элементов в файле. Вернёмся к нашему примеру. От корня отходят три дочерних элемента:​ node1, node2 и node3. Дочерние элементы имеют общий корень,​ а node3 является родителем для node3sub1. Каждый XML-файл – это древовидная структура,​ начинающаяся с корня и ответвляющаяся от него. Он ДОЛЖЕН иметь корневой элемент – родитель для всех других элементов в файле. Вернёмся к нашему примеру. От корня отходят три дочерних элемента:​ node1, node2 и node3. Дочерние элементы имеют общий корень,​ а node3 является родителем для node3sub1.
Строка 48: Строка 52:
 Имеется корневой элемент «people», содержащий два дочерних – «person». Каждый элемент «person» содержит 6 дочерних элементов:​ «firstname»,​ «lastname»,​ «gender», «address»,​ «city» и «state». На первый взгляд,​ XML-файл можно рассматривать как базу данных (вспомните несколько последних лекций),​ и это верное предположение. Некоторые приложения используют XML-файлы как простую структуру базы данных. Не составит труда написать программу для чтения XML-файла. Она должна открыть файл, прочитать его построчно и, в зависимости от элемента,​ использовать заключённые в нём данные,​ а затем закрыть файл. Однако есть и более эффективные способы. Имеется корневой элемент «people», содержащий два дочерних – «person». Каждый элемент «person» содержит 6 дочерних элементов:​ «firstname»,​ «lastname»,​ «gender», «address»,​ «city» и «state». На первый взгляд,​ XML-файл можно рассматривать как базу данных (вспомните несколько последних лекций),​ и это верное предположение. Некоторые приложения используют XML-файлы как простую структуру базы данных. Не составит труда написать программу для чтения XML-файла. Она должна открыть файл, прочитать его построчно и, в зависимости от элемента,​ использовать заключённые в нём данные,​ а затем закрыть файл. Однако есть и более эффективные способы.
  
-В следующем примере мы воспользуемся модулем библиотеки под названием ElementTree. Его можно получить непосредственно из Synaptic, установив python-elementtree. Однако я предпочитаю устанавливать с сайта ElementTree (http://​effbot.org/​ downloads/#​elementtree) и непосредственно загружать файл-исходник (elementtree-1.2.6-20050316.tar.gz). После загрузки я с помощью менеджера пакетов извлекаю его во временную папку. Затем в этой папке выполняю «sudo python setup.py install». Эта команда помещает файлы в общую папку python, поэтому в дальнейшем у меня есть возможность использовать модуль и в python 2.5, и в 2.6. Итак, приступим к работе! Создайте папку, которая будет содержать код этого месяца,​ скопируйте приведённые выше данные в XML-формате в ваш любимый текстовой редактор и сохраните их в эту папку под именем «xmlsample1.xml».+В следующем примере мы воспользуемся модулем библиотеки под названием ElementTree. Его можно получить непосредственно из Synaptic, установив python-elementtree. Однако я предпочитаю устанавливать с сайта ElementTree (http://​effbot.org/​downloads/#​elementtree) и непосредственно загружать файл-исходник (elementtree-1.2.6-20050316.tar.gz). После загрузки я с помощью менеджера пакетов извлекаю его во временную папку. Затем в этой папке выполняю «sudo python setup.py install». Эта команда помещает файлы в общую папку python, поэтому в дальнейшем у меня есть возможность использовать модуль и в python 2.5, и в 2.6. Итак, приступим к работе! Создайте папку, которая будет содержать код этого месяца,​ скопируйте приведённые выше данные в XML-формате в ваш любимый текстовой редактор и сохраните их в эту папку под именем «xmlsample1.xml».
  
 Поговорим о нашем коде. В первую очередь хочется протестировать установленный модуль ElementTree. Поговорим о нашем коде. В первую очередь хочется протестировать установленный модуль ElementTree.
  
-import elementtree.ElementTree as ET+<​code>​import elementtree.ElementTree as ET
  
 tree = ET.parse('​xmlsample1.xml'​) tree = ET.parse('​xmlsample1.xml'​)
  
-ET.dump(tree)+ET.dump(tree)</​code>​
  
 Запустив эту программу,​ мы получим нечто похожее на то, что представлено ниже. Запустив эту программу,​ мы получим нечто похожее на то, что представлено ниже.
Строка 64: Строка 68:
 Теперь заменим наш код на следующий:​ Теперь заменим наш код на следующий:​
  
-import elementtree.ElementTree as ET+<​code>​import elementtree.ElementTree as ET
  
 tree = ET.parse('​xmlsample1.xml'​) tree = ET.parse('​xmlsample1.xml'​)
Строка 74: Строка 78:
 for dat in p: for dat in p:
  
-print "​Элемент:​ %s - Данные:​ %s" %(dat.tag,​dat.text)+print "​Элемент:​ %s - Данные:​ %s" %(dat.tag,​dat.text)</​code>​
  
 Запустите код снова. Результат будет таким: Запустите код снова. Результат будет таким:
  
-/​usr/​bin/​python -u "/​home/​greg/​Documents/​articles/​xml/​reader1.py"​+**/​usr/​bin/​python -u "/​home/​greg/​Documents/​articles/​xml/​reader1.py"​**
  
-Элемент:​ firstname - Данные:​ Саманта +  * Элемент:​ firstname - Данные:​ Саманта 
-Элемент:​ lastname - Данные:​ Фэроу +  ​* ​Элемент:​ lastname - Данные:​ Фэроу 
-Элемент:​ gender - Данные:​ Женский +  ​* ​Элемент:​ gender - Данные:​ Женский 
-Элемент:​ address - Данные:​ ул. Мэйн, д. 123 +  ​* ​Элемент:​ address - Данные:​ ул. Мэйн, д. 123 
-Элемент:​ city - Данные:​ Дэнвер +  ​* ​Элемент:​ city - Данные:​ Дэнвер 
-Элемент:​ state - Данные:​ Колорадо +  ​* ​Элемент:​ state - Данные:​ Колорадо 
-Элемент:​ firstname - Данные:​ Стив +  ​* ​Элемент:​ firstname - Данные:​ Стив 
-Элемент:​ lastname - Данные:​ Левон +  ​* ​Элемент:​ lastname - Данные:​ Левон 
-Элемент:​ gender - Данные:​ Мужской +  ​* ​Элемент:​ gender - Данные:​ Мужской 
-Элемент:​ address - Данные:​ Бульвар Арапахо,​ 332120 +  ​* ​Элемент:​ address - Данные:​ Бульвар Арапахо,​ 332120 
-Элемент:​ city - Данные:​ Дэнвер +  ​* ​Элемент:​ city - Данные:​ Дэнвер 
-Элемент:​ state - Данные:​ Колорадо+  ​* ​Элемент:​ state - Данные:​ Колорадо
  
 Теперь каждая порция данных выводится напротив имени тэга. Эти данные можно легко распечатать. Итак, посмотрим,​ что делает программа. Модуль ElementTree проанализировал файл и поместил результаты в объект tree. Затем ElementTree нашёл все вхождения тэга person. В нашем примере таких элементов оказалось два, но их могло быть 1 или 1000. Элемент person – дочерний к корневому элементу people. Все данные были разбиты на порции. Затем мы создали простой цикл, перебирающий объекты person. Вложенный в него цикл перебирает данные каждого элемента person, и на экран выводятся результаты,​ показывающие имя элемента (.tag) и данные (.text). Теперь каждая порция данных выводится напротив имени тэга. Эти данные можно легко распечатать. Итак, посмотрим,​ что делает программа. Модуль ElementTree проанализировал файл и поместил результаты в объект tree. Затем ElementTree нашёл все вхождения тэга person. В нашем примере таких элементов оказалось два, но их могло быть 1 или 1000. Элемент person – дочерний к корневому элементу people. Все данные были разбиты на порции. Затем мы создали простой цикл, перебирающий объекты person. Вложенный в него цикл перебирает данные каждого элемента person, и на экран выводятся результаты,​ показывающие имя элемента (.tag) и данные (.text).
Строка 105: Строка 109:
 Первая строка обычно сообщает,​ что это проверенный XML-файл,​ её можно проигнорировать. Следующая строка,​ начинающаяся с «loc», является корневым элементом и содержит атрибуты «version» и «src». Выше я отмечал,​ что атрибуты иногда используются в файлах. В дальнейшем мы ещё будем иметь дело с ними в этом файле. Корневой элемент тут также может быть проигнорирован. Следующая строка содержит тэг дочернего элемента – маршрутной точки (waypoint). (Маршрутная точка – это место расположения,​ где можно найти тайник). Из этого элемента можно получить важные сведения:​ наименование тайника,​ координаты (долготу и широту),​ тип тайника и ссылку на интернет-страницу с дополнительной информацией. Элемент с именем содержит кучу полезной информации,​ но проводить её структурный анализ придётся самостоятельно. Давайте теперь создадим программу для чтения и отображения файла cache.loc, назвав её readacache.py. Начнём с импорта модуля и команд для структурного анализа из предыдущего примера. Первая строка обычно сообщает,​ что это проверенный XML-файл,​ её можно проигнорировать. Следующая строка,​ начинающаяся с «loc», является корневым элементом и содержит атрибуты «version» и «src». Выше я отмечал,​ что атрибуты иногда используются в файлах. В дальнейшем мы ещё будем иметь дело с ними в этом файле. Корневой элемент тут также может быть проигнорирован. Следующая строка содержит тэг дочернего элемента – маршрутной точки (waypoint). (Маршрутная точка – это место расположения,​ где можно найти тайник). Из этого элемента можно получить важные сведения:​ наименование тайника,​ координаты (долготу и широту),​ тип тайника и ссылку на интернет-страницу с дополнительной информацией. Элемент с именем содержит кучу полезной информации,​ но проводить её структурный анализ придётся самостоятельно. Давайте теперь создадим программу для чтения и отображения файла cache.loc, назвав её readacache.py. Начнём с импорта модуля и команд для структурного анализа из предыдущего примера.
  
-import elementtree.ElementTree as ET+<​code>​import elementtree.ElementTree as ET
  
-tree = ET.parse('​Cache.loc'​)+tree = ET.parse('​Cache.loc'​)</​code>​
  
 Нам необходимо получить только данные,​ находящиеся внутри тэга waypoint. Для этого мы используем функцию .find внутри модуля ElementTree. Результаты работы будут сохранены в объекте w. Нам необходимо получить только данные,​ находящиеся внутри тэга waypoint. Для этого мы используем функцию .find внутри модуля ElementTree. Результаты работы будут сохранены в объекте w.
  
-w = tree.find('​.//​waypoint'​)+<​code>​w = tree.find('​.//​waypoint'​)</​code>​
  
 Затем нам необходимо просмотреть все данные,​ для чего используется цикл for. В теле цикла мы ищем элементы name (имя), coord (координаты),​ type (тип) и link (ссылка). На основании содержащихся в тэге данных,​ мы извлекаем информацию,​ чтобы распечатать её в дальнейшем. Затем нам необходимо просмотреть все данные,​ для чего используется цикл for. В теле цикла мы ищем элементы name (имя), coord (координаты),​ type (тип) и link (ссылка). На основании содержащихся в тэге данных,​ мы извлекаем информацию,​ чтобы распечатать её в дальнейшем.
  
-for w1 in w: +<​code>​for w1 in w: 
- if w1.tag == "​name":​+ if w1.tag == "​name":​</​code>​
  
 Просмотрим,​ какие данные можно извлечь из тэга name. Просмотрим,​ какие данные можно извлечь из тэга name.
- +<​code>​ 
-<name id="​N02CAC"><​![CDATA[Возьмите Фотографии озера Виноградной лозы, сделанные g_phillips+<name id="​N02CAC"><​![CDATA[Возьмите Фотографии озера ​ 
 +Виноградной лозы, сделанные g_phillips
  
 Тайник открыт:​ не ограничено Тайник открыт:​ не ограничено
Строка 131: Строка 136:
  
 Местность:​ 2.0]]></​name>​ Местность:​ 2.0]]></​name>​
 +</​code>​
 Это одна очень длинная строка. Идентификатор id установлен как атрибут. Имя тайника – это часть строки после «CDATA» и до «Тайник открыт:​». Мы разделим Это одна очень длинная строка. Идентификатор id установлен как атрибут. Имя тайника – это часть строки после «CDATA» и до «Тайник открыт:​». Мы разделим
-строку на несколько более мелких частей. ​Получить часть строки можно, используя следующий код: +строку на несколько более мелких частей. ​
- +
  
-newstring = oldstring[startposition:​endposition]+<​code>​newstring = oldstring[startposition:​endposition]</​code>​
  
 Итак, приведенный код можно использовать для извлечения необходимой информации. Итак, приведенный код можно использовать для извлечения необходимой информации.
Строка 205: Строка 208:
 <loc version="​1.0"​ src="​NaviCache">​ <loc version="​1.0"​ src="​NaviCache">​
    <​waypoint>​    <​waypoint>​
-      <name id="​N02CAC"><​![CDATA[Take Goofy Pictures at Grapevine Lake  by g_phillips+      <name id="​N02CAC"><​![CDATA[Take Goofy  
 +      ​Pictures at Grapevine Lake  by g_phillips
 Open Cache: Unrestricted Open Cache: Unrestricted
 Cache Type: Normal Cache Type: Normal
Строка 213: Строка 217:
       <​coord ​ lat="​32.9890166666667" ​ lon="​-97.0728833333333"​ />       <​coord ​ lat="​32.9890166666667" ​ lon="​-97.0728833333333"​ />
       <​type>​Geocache</​type>​       <​type>​Geocache</​type>​
-      <link text="​Cache Details">​http://​www.navicache.com/​cgi-bin/​db/​displaycache2.pl?​CacheID=11436</​link>​+      <​link ​ 
 +      ​text="​Cache Details">​ 
 +      ​http://​www.navicache.com/​cgi-bin/​db/​displaycache2.pl 
 +      ​?​CacheID=11436</​link>​
    </​waypoint>​    </​waypoint>​
 </​loc>​ </​loc>​
Строка 221: Строка 228:
 <​code>​ <​code>​
 # Get text of cache name up to the phrase "Open Cache: " # Get text of cache name up to the phrase "Open Cache: "
-CacheName = w1.text[:​w1.text.find("​Open Cache: ")-1]+CacheName = w1.text[:​w1.text.find 
 +("Open Cache: ")-1]
 # Get the text between "Open Cache: " and "Cache Type: " # Get the text between "Open Cache: " and "Cache Type: "
-OpenCache = w1.text[w1.text.find("​Open Cache: "​)+12:​w1.text.find("​Cache Type: ")-1]+OpenCache = w1.text[w1.text.find 
 +("Open Cache: "​)+12:​w1.text.find("​Cache Type: ")-1]
 # More of the same # More of the same
-CacheType = w1.text[w1.text.find("​Cache Type: "​)+12:​w1.text.find("​Cache Size: "​)-1] +CacheType = w1.text[w1.text.find 
-CacheSize = w1.text[w1.text.find("​Cache Size: "​)+12:​w1.text.find("​Difficulty:​ "​)-1] +("​Cache Type: "​)+12:​w1.text.find 
-Difficulty= w1.text[w1.text.find("​Difficulty:​ "​)+12:​w1.text.find("​Terrain ​  : "​)-1] +("​Cache Size: "​)-1] 
-Terrain =   ​w1.text[w1.text.find("​Terrain ​  : "​)+12:​]+CacheSize = w1.text[w1.text.find 
 +("​Cache Size: "​)+12:​w1.text.find 
 +("​Difficulty:​ "​)-1] 
 +Difficulty= w1.text[w1.text.find 
 +("​Difficulty:​ "​)+12:​w1.text.find 
 +("​Terrain ​  : "​)-1] 
 +Terrain =   ​w1.text[w1.text.find 
 +("​Terrain ​  : "​)+12:​]
 </​code>​ </​code>​
  
Строка 269: Строка 285:
     if w1.tag == "​name":​     if w1.tag == "​name":​
         # Get text of cache name up to the phrase "Open Cache: "         # Get text of cache name up to the phrase "Open Cache: "
-        CacheName = w1.text[:​w1.text.find("​Open Cache: "​)-1] +        CacheName = w1.text[:​w1.text.find 
-        # Get the text between "Open Cache: " and "Cache Type: " +        ​("Open Cache: "​)-1] 
-        OpenCache = w1.text[w1.text.find("​Open Cache: "​)+12:​w1.text.find("​Cache Type: ")-1]+        # Get the text between ​ 
 +        ​"Open Cache: " and "Cache Type: " 
 +        OpenCache = w1.text[w1.text.find 
 +        ​("Open Cache: "​)+12:​w1.text.find 
 +        ​("​Cache Type: ")-1]
         # More of the same         # More of the same
-        CacheType = w1.text[w1.text.find("​Cache Type: "​)+12:​w1.text.find("​Cache Size: "​)-1] +        CacheType = w1.text[w1.text.find 
-        CacheSize = w1.text[w1.text.find("​Cache Size: "​)+12:​w1.text.find("​Difficulty:​ "​)-1] +        ​("​Cache Type: "​)+12:​w1.text.find 
-        Difficulty= w1.text[w1.text.find("​Difficulty:​ "​)+12:​w1.text.find("​Terrain ​  : "​)-1] +        ​("​Cache Size: "​)-1] 
-        Terrain =   ​w1.text[w1.text.find("​Terrain ​  : "​)+12:​]+        CacheSize = w1.text[w1.text.find 
 +        ​("​Cache Size: "​)+12:​w1.text.find 
 +        ​("​Difficulty:​ "​)-1] 
 +        Difficulty= w1.text[w1.text.find 
 +        ​("​Difficulty:​ "​)+12:​w1.text.find 
 +        ​("​Terrain ​  : "​)-1] 
 +        Terrain =   ​w1.text[w1.text.find 
 +        ​("​Terrain ​  : "​)+12:​]
         if w1.keys():         if w1.keys():
             for name,value in w1.items():             for name,value in w1.items():