Язык программирования Python
Язык программирования Python читать книгу онлайн
Курс посвящен одному из бурно развивающихся и популярных в настоящее время сценарных языков программирования — Python. Язык Python позволяет быстро создавать как прототипы программных систем, так и сами программные системы, помогает в интеграции программного обеспечения для решения производственных задач. Python имеет богатую стандартную библиотеку и большое количество модулей расширения практически для всех нужд отрасли информационных технологий. Благодаря ясному синтаксису изучение языка не составляет большой проблемы. Написанные на нем программы получаются структурированными по форме, и в них легко проследить логику работы. На примере языка Python рассматриваются такие важные понятия как: объектно–ориентированное программирование, функциональное программирование, событийно–управляемые программы (GUI–приложения), форматы представления данных (Unicode, XML и т.п.). Возможность диалогового режима работы интерпретатора Python позволяет существенно сократить время изучения самого языка и перейти к решению задач в соответствующих предметных областях. Python свободно доступен для многих платформ, а написанные на нем программы обычно переносимы между платформами без изменений. Это обстоятельство позволяет применять для изучения языка любую имеющуюся аппаратную платформу.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Здесь была использована СУБД SQLite и соответствующий модуль расширения Python для сопряжения с этой СУБД — sqlite, так как он поддерживает DB–API 2.0 и достаточно прост в установке. С его помощью были продемонстрированы основные приемы работы с базой данных: создание и наполнение таблиц, выполнение выборок и анализ полученных данных.
В конце лекции дан список других пакетов и модулей, которые позволяют Python–программе работать со многими современными СУБД.
11. Лекция: Многопоточные вычисления.
В этой лекции рассматриваются вопросы взаимодействия потоков (нитей) в рамках одной программы. Вводятся основные понятия (семафоры, очереди, блокировки). Делается попытка объяснить особенности параллельного программирования на основе модели многопоточности.
О потоках управления
В современной операционной системе, даже не выполняющей ничего особенного, могут одновременно работать несколько процессов (processes). Например, при запуске программы запускается новый процесс. Функции для управления процессами можно найти в стандартном модуле os языка Python. Здесь же речь пойдет о потоках.
Потоки управления (threads) образуются и работают в рамках одного процесса. В однопоточном приложении (программе, которая не использует дополнительных потоков) имеется только один поток управления. Говоря упрощенно, при запуске программы этот поток последовательно исполняет встречаемые в программе операторы, направляясь по одной из альтернативных ветвей оператора выбора, проходит через тело цикла нужное число раз, выбирается к месту обработки исключения при возбуждении исключения. В любой момент времени интерпретатор Python знает, какую команду исполнить следующей. После исполнения команды становится известно, какой команде передать управление. Эта ниточка непрерывна в ходе выполнения программы и обрывается только по ее завершении.
Теперь можно представить себе, что в некоторой точке программы ниточка раздваивается, и каждый поток идет своим путем. Каждый из образовавшихся потоков может в дальнейшем еще несколько раз раздваиваться. (При этом один из потоков всегда остается главным, и его завершение означает завершение всей программы.) В каждый момент времени интерпретатор знает, какую команду какой поток должен выполнить, и уделяет кванты времени каждому потоку. Такое, казалось бы, незначительное усложнение механизма выполнения программы на самом деле требует качественных изменений в программе — ведь деятельность потоков должна быть согласована. Нельзя допускать, чтобы потоки одновременно изменяли один и тот же объект, результат такого изменения, скорее всего, нарушит целостность объекта.
Одним из классических средств согласования потоков являются объекты, называемые семафорами. Семафоры не допускают выполнения некоторого участка кода несколькими потоками одновременно. Самый простой семафор — замок (lock) или mutex (от английского mutually exclusive, взаимоисключающий). Для того чтобы поток мог продолжить выполнение кода, он должен сначала захватить замок. После захвата замка поток выполняет определенный участок кода и потом освобождает замок, чтобы другой поток мог его получить и пройти дальше к выполнению охраняемого замком участку программы. Поток, столкнувшись с занятым другим потоком замком, обычно ждет его освобождения.
Поддержка многопоточности в языке Python доступна через использование ряда модулей. В стандартном модуле threading определены нужные для разработки многопоточной (multithreading) программы классы: несколько видов семафоров (классы замков Lock, RLock и класс Semaphore) и другие механизмы взаимодействия между потоками (классы Event и Condition), класс Timer для запуска функции по прошествии некоторого времени. Модуль Queue реализует очередь, которой могут пользоваться сразу несколько потоков. Для создания и (низкоуровневого) управления потоками в стандартном модуле thread определен класс Thread.
Пример многопоточной программы
В следующем примере создается два дополнительных потока, которые выводят на стандартный вывод каждый свое:
Листинг
import threading
def proc(n):
print «Процесс», n
p1 = threading.Thread(target=proc, name=«t1», args=[«1»])
p2 = threading.Thread(target=proc, name=«t2», args=[«2»])
p1.start()
p2.start()
Сначала получается два объекта класса Thread, которые затем и запускаются с различными аргументами. В данном случае в потоках работает одна и та же функция proc(), которой передается один аргумент, заданный в именованном параметре args конструктора класса Thread. Нетрудно догадаться, что метод start() служит для запуска нового потока. Таким образом, в приведенном примере работают три потока: основной и два дополнительных (с именами «t1» и «t2»).
Функции модуля threading
В модуле threading, который здесь используется, есть функции, позволяющие получить информацию о потоках:
activeCount() Возвращает количество активных в настоящий момент экземпляров класса Thread. Фактически, это len(threading.enumerate()).
currentThread() Возвращает текущий объект–поток, то есть соответствующий потоку управления, который вызвал эту функцию. Если поток не был создан через модуль threading, будет возвращен объект–поток с сокращенной функциональностью (dummy thread object).
enumerate() Возвращает список активных потоков. Завершившиеся и еще не начатые потоки не входят в список.
Класс Thread
Экземпляры класса threading.Thread представляют потоки Python–программы. Задать действия, которые будут выполняться в потоке, можно двумя способами: передать конструктору класса исполняемый объект и аргументы к нему или путем наследования получить новый класс с переопределенным методом run(). Первый способ был рассмотрен в примере выше. Конструктор класса threading.Thread имеет следующие аргументы:
Листинг
Thread(group, target, name, args, kwargs)
Здесь group — группа потоков (пока что не используется, должен быть равен None), target — объект, который будет вызван в методе run(), name — имя потока, args и kwargs — последовательность и словарь позиционных и именованных параметров (соответственно) для вызова заданного в параметре target объекта. В примере выше были использованы только позиционные параметры, но то же самое можно было выполнить и с применением именованных параметров:
Листинг
import threading
def proc(n):
print «Процесс», n
p1 = threading.Thread(target=proc, name=«t1», kwargs={«n»: «1»})
p2 = threading.Thread(target=proc, name=«t2», kwargs={«n»: «2»})
p1.start()
p2.start()
То же самое можно проделать через наследование от класса threading.Thread с определением собственного конструктора и метода run():
Листинг
import threading
class T(threading.Thread):
def __init__(self, n):
threading.Thread.__init__(self, name=«t» + n)
self.n = n
def run(self):
print «Процесс», self.n
p1 = T(«1»)
p2 = T(«2»)
p1.start()
p2.start()
Самое первое, что необходимо сделать в конструкторе — вызвать конструктор базового класса. Как и раньше, для запуска потока нужно выполнить метод start() объекта–потока, что приведет к выполнению действий в методе run().
Жизнью потоков можно управлять вызовом методов:
start()Дает потоку жизнь.
run()Этот метод представляет действия, которые должны быть выполнены в потоке.
join([timeout])Поток, который вызывает этот метод, приостанавливается, ожидая завершения потока, чей метод вызван. Параметр timeout (число с плавающей точкой) позволяет указать время ожидания (в секундах), по истечении которого приостановленный поток продолжает свою работу независимо от завершения потока, чей метод join был вызван. Вызывать join() некоторого потока можно много раз. Поток не может вызвать метод join() самого себя. Также нельзя ожидать завершения еще не запущенного потока. Слово «join» в переводе с английского означает «присоединить», то есть, метод, вызвавший join(), желает, чтобы поток по завершении присоединился к вызывающему метод потоку.