10. Brief Tour of the Standard Library
**************************************


10.1. Operating System Interface
================================

Модуль "os" предоставляет десятки функций для взаимодействия с
операционной системой:

   >>> import os
   >>> os.getcwd()      # Return the current working directory
   'C:\\Python312'
   >>> os.chdir('/server/accesslogs')   # Change current working directory
   >>> os.system('mkdir today')   # Run the command mkdir in the system shell
   0

Для импорта этого модуля используйте стиль "import os", а не "from os
import *". В противном случае "os.open()" затенит встроенную функцию
"open()", а они работают по-разному.

Встроенные функции "dir()" и "help()" полезны как интерактивные
помощники при работе с большими модулями, вроде "os":

   >>> import os
   >>> dir(os)
   <возвращает список всех функций модуля>
   >>> help(os)
   <возвращает подробную справку, собранную из docstring’ов модуля>

For daily file and directory management tasks, the "shutil" module
provides a higher level interface that is easier to use:

   >>> import shutil
   >>> shutil.copyfile('data.db', 'archive.db')
   'archive.db'
   >>> shutil.move('/build/executables', 'installdir')
   'installdir'


10.2. File Wildcards
====================

Модуль "glob" предоставляет функцию для получения списка файлов по
указанному шаблону:

   >>> import glob
   >>> glob.glob('*.py')
   ['primes.py', 'random.py', 'quote.py']


10.3. Command Line Arguments
============================

Common utility scripts often need to process command line arguments.
These arguments are stored in the "sys" module's *argv* attribute as a
list.  For instance, let's take the following "demo.py" file:

   # Файл demo.py
   import sys
   print(sys.argv)

Вот результат выполнения "python demo.py one two three" в командной
строке:

   ['demo.py', 'one', 'two', 'three']

The "argparse" module provides a more sophisticated mechanism to
process command line arguments.  The following script extracts one or
more filenames and an optional number of lines to be displayed:

   import argparse

   parser = argparse.ArgumentParser(
       prog='top',
       description='Показать верхние строки из каждого файла')
   parser.add_argument('filenames', nargs='+')
   parser.add_argument('-l', '--lines', type=int, default=10)
   args = parser.parse_args()
   print(args)

При запуске из командной строки как "python top.py --lines=5 alpha.txt
beta.txt", скрипт установит "args.lines" в "5", а "args.filenames" в
"['alpha.txt', 'beta.txt']".


10.4. Error Output Redirection and Program Termination
======================================================

Модуль "sys" содержит также атрибуты *stdin*, *stdout* и *stderr*.
Последний полезен для вывода предупреждений и сообщений об ошибках,
которые должны быть видны даже при перенаправленном *stdout*:

   >>> sys.stderr.write('Предупреждение, файл журнала не найден — начинаю новый\n')
   Предупреждение, файл журнала не найден — начинаю новый

Самый простой способ завершить программу -- вызвать "sys.exit()".


10.5. String Pattern Matching
=============================

Модуль "re" предоставляет инструменты регулярных выражений для
продвинутой обработки строк. Для сложного сопоставления и
преобразования регулярные выражения предлагают лаконичные и
оптимизированные решения:

   >>> import re
   >>> re.findall(r'\bп[а-я]*', 'прыгнул кот или пушистый попугай')
   ['прыгнул', 'пушистый', 'попугай']
   >>> re.sub(r'(\b[а-я]+) \1', r'\1', 'кот на на крыше')
   'кот на крыше'

Если нужны только простые возможности, методы строк предпочтительнее,
потому что их проще читать и отлаживать:

   >>> 'чай для два'.replace('два', 'двоих')
   'чай для двоих'


10.6. Математика
================

Модуль "math" даёт доступ к функциям стандартной библиотеки C для
вычислений с плавающей точкой:

   >>> import math
   >>> math.cos(math.pi / 4)
   0.70710678118654757
   >>> math.log(1024, 2)
   10.0

Модуль "random" предоставляет инструменты для выполнения случайных
выборок:

   >>> import random
   >>> random.choice(['apple', 'pear', 'banana'])
   'apple'
   >>> random.sample(range(100), 10)   # sampling without replacement
   [30, 83, 16, 4, 8, 81, 41, 50, 18, 33]
   >>> random.random()    # random float
   0.17970987693706186
   >>> random.randrange(6)    # random integer chosen from range(6)
   4

Модуль "statistics" позволяет вычислять базовые статистические
характеристики (среднее, медиану, дисперсию и т. п.) для числовых
данных:

   >>> import statistics
   >>> data = [2.75, 1.75, 1.25, 0.25, 0.5, 1.25, 3.5]
   >>> statistics.mean(data)
   1.6071428571428572
   >>> statistics.median(data)
   1.25
   >>> statistics.variance(data)
   1.3720238095238095

Проект SciPy <https://scipy.org> содержит большое количество других
модулей для численных вычислений.


10.7. Internet Access
=====================

Есть множество модулей, предназначенных для доступа в интернет и
работы с его протоколами. Два самых простых модуля: "urllib.request" —
для получения данных по URL и "smtplib" — для отправки электронной
почты:

   >>> from urllib.request import urlopen
   >>> with urlopen('http://worldtimeapi.org/api/timezone/etc/UTC.txt') as response:
   ...     for line in response:
   ...         line = line.decode()             # Convert bytes to a str
   ...         if line.startswith('datetime'):
   ...             print(line.rstrip())         # Remove trailing newline
   ...
   datetime: 2022-01-01T01:36:47.689215+00:00

   >>> import smtplib
   >>> server = smtplib.SMTP('localhost')
   >>> server.sendmail('soothsayer@example.org', 'jcaesar@example.org',
   ... """To: jcaesar@example.org
   ... From: soothsayer@example.org
   ...
   ... Beware the Ides of March.
   ... """)
   >>> server.quit()

(Обратите внимание, что для второго примера требуется почтовый сервер,
запущенный на localhost.)


10.8. Dates and Times
=====================

Модуль "datetime" предоставляет классы для манипуляции с датами и
временем как простыми, так и сложными способами. Хотя поддерживается
арифметика дат и времени, основное внимание в реализации уделяется
эффективному извлечению элементов для форматирования и обработки
выходных данных. Модуль также поддерживает объекты, учитывающие
часовой пояс.

   >>> # dates are easily constructed and formatted
   >>> from datetime import date
   >>> now = date.today()
   >>> now
   datetime.date(2003, 12, 2)
   >>> now.strftime("%m-%d-%y. %d %b %Y is a %A on the %d day of %B.")
   '12-02-03. 02 Dec 2003 is a Tuesday on the 02 day of December.'

   >>> # dates support calendar arithmetic
   >>> birthday = date(1964, 7, 31)
   >>> age = now - birthday
   >>> age.days
   14368


10.9. Data Compression
======================

Распространённые форматы архивирования и сжатия данных напрямую
поддерживаются модулями, включая "zlib", "gzip", "bz2", "lzma",
"zipfile" и "tarfile".

   >>> import zlib
   >>> s = b'witch which has which witches wrist watch'
   >>> len(s)
   41
   >>> t = zlib.compress(s)
   >>> len(t)
   37
   >>> zlib.decompress(t)
   b'witch which has which witches wrist watch'
   >>> zlib.crc32(s)
   226805979


10.10. Performance Measurement
==============================

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

Например, может быть заманчивым использовать распаковку и упаковку
кортежей вместо традиционного подхода к обмену значений между
переменными. Модуль "timeit" быстро показывает скромное преимущество в
производительности:

   >>> from timeit import Timer
   >>> Timer('t=a; a=b; b=t', 'a=1; b=2').timeit()
   0.57535828626024577
   >>> Timer('a,b = b,a', 'a=1; b=2').timeit()
   0.54962537085770791

В отличие от высокой детализации "timeit", модули "profile" и "pstats"
предоставляют инструменты для выявления критичных по времени участков
в более крупных блоках кода.


10.11. Quality Control
======================

Один из подходов к разработке программного обеспечения высокого
качества — писать тесты для каждой функции по мере их разработки и
регулярно запускать их.

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

   def average(values):
       """Вычисляет среднее арифметическое списка чисел.

       >>> print(average([20, 30, 70]))
       40.0
       """
       return sum(values) / len(values)

   import doctest
   doctest.testmod()   # автоматически проверяет встроенные тесты

Модуль "unittest" не так просто в использовании, как "doctest", но
позволяет поддерживать более полный набор тестов в отдельном файле:

   import unittest

   class TestStatisticalFunctions(unittest.TestCase):

       def test_average(self):
           self.assertEqual(average([20, 30, 70]), 40.0)
           self.assertEqual(round(average([1, 5, 7]), 1), 4.3)
           with self.assertRaises(ZeroDivisionError):
               average([])
           with self.assertRaises(TypeError):
               average(20, 30, 70)

   unittest.main()  # Запуск с командной строки вызывает все тесты


10.12. Batteries Included
=========================

Python придерживается философии «батарейки включены в комплект». Это
лучше всего проявляется в продвинутых и надёжных возможностях его
крупных пакетов. Например:

* Модули "xmlrpc.client" и "xmlrpc.server" делают реализацию
  удалённого вызова процедур почти тривиальной задачей. Несмотря на
  название модулей, не требуется прямых знаний или обработки XML.

* The "email" package is a library for managing email messages,
  including MIME and other **RFC 2822**-based message documents.
  Unlike "smtplib" and "poplib" which actually send and receive
  messages, the email package has a complete toolset for building or
  decoding complex message structures (including attachments) and for
  implementing internet encoding and header protocols.

* Пакет "json" предоставляет надёжные средства для работы с этим
  популярным форматом обмена данными. Модуль "csv" поддерживает прямое
  чтение и запись файлов в формате CSV (Comma-Separated Value), широко
  используемом в базах данных и электронных таблицах. Обработка XML
  осуществляется пакетами "xml.etree.ElementTree", "xml.dom" и
  "xml.sax". Вместе эти модули и пакеты значительно упрощают обмен
  данными между приложениями Python и другими инструментами.

* Модуль "sqlite3" является обёрткой для библиотеки базы данных
  SQLite, предоставляя постоянное хранилище, которое можно обновлять и
  использовать со слегка нестандартным синтаксисом SQL.

* Поддержка интернационализации обеспечивается рядом модулей, включая
  "gettext", "locale", и пакетом "codecs".
