# 10. Коротка екскурсія Стандартною бібліотекою

## 10.1. Інтерфейс операційної системи

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

    >>> import os
    >>> os.getcwd()      # Return the current working directory
    'C:\\Python311'
    >>> 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)
    <returns a list of all module functions>
    >>> help(os)
    <returns an extensive manual page created from the module's docstrings>

Для щоденних завдань керування файлами та каталогами модуль `shutil` надає інтерфейс вищого рівня, який легше використовувати:

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

## 10.2. Символи підстановки файлів

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

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

## 10.3. Аргументи командного рядка

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 the following output results from running `python demo.py one two three` at the command line:

    >>> import sys
    >>> print(sys.argv)
    ['demo.py', 'one', 'two', 'three']

Модуль `argparse` забезпечує більш складний механізм обробки аргументів командного рядка. Наступний сценарій витягує одне або кілька імен файлів і необов’язкову кількість рядків для відображення:

    import argparse

    parser = argparse.ArgumentParser(
        prog='top',
        description='Show top lines from each file')
    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. Перенаправлення виводу помилки та завершення програми

Модуль `sys` також має атрибути для stdin, stdout і stderr. Останній корисний для видачі попереджень і повідомлень про помилки, щоб зробити їх видимими, навіть якщо stdout було перенаправлено:

    >>> sys.stderr.write('Warning, log file not found starting a new one\n')
    Warning, log file not found starting a new one

Найпряміший спосіб завершити сценарій – це використати `sys.exit()`.

## 10.5. Відповідність шаблону рядка

Модуль `re` надає інструменти регулярних виразів для розширеної обробки рядків. Для складних відповідностей і маніпуляцій регулярні вирази пропонують короткі, оптимізовані рішення:

    >>> import re
    >>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')
    ['foot', 'fell', 'fastest']
    >>> re.sub(r'(\b[a-z]+) \1', r'\1', 'cat in the the hat')
    'cat in the hat'

Коли потрібні лише прості можливості, краще використовувати рядкові методи, оскільки їх легше читати та налагоджувати:

    >>> 'tea for too'.replace('too', 'two')
    'tea for two'

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

The `math` module gives access to the underlying C library functions for floating point math:

    >>> 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. Доступ в інтернет

Існує ряд модулів для доступу до Інтернету та обробки Інтернет-протоколів. Двома найпростішими є `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()

(Зверніть увагу, що для другого прикладу потрібен поштовий сервер, який працює на локальному хості.)

## 10.8. Дати та час

Модуль `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. Стиснення даних

Загальні формати архівування та стиснення даних безпосередньо підтримуються такими модулями, як: `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. Вимірювання ефективності

Деякі користувачі Python відчувають глибокий інтерес до знання відносної ефективності різних підходів до однієї проблеми. 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. Контроль якості

Одним із підходів до розробки високоякісного програмного забезпечення є написання тестів для кожної функції в міру її розробки та часте виконання цих тестів у процесі розробки.

Модуль `doctest` надає інструмент для сканування модуля та перевірки тестів, вбудованих у рядки документів програми. Побудова тесту така ж проста, як вирізання та вставлення типового виклику разом із його результатами в рядок документації. Це покращує документацію, надаючи користувачеві приклад, і це дозволяє модулю doctest переконатися, що код залишається вірним документації:

    def average(values):
        """Computes the arithmetic mean of a list of numbers.

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

    import doctest
    doctest.testmod()   # automatically validate the embedded tests

Модуль `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()  # Calling from the command line invokes all tests

## 10.12. Батарейки в комплекті

Python має філософію «батареї включені». Це найкраще видно через складні та надійні можливості його більших пакетів. Наприклад:

- Модулі `xmlrpc.client` і `xmlrpc.server` роблять реалізацію викликів віддалених процедур майже тривіальним завданням. Незважаючи на назви модулів, не потрібні прямі знання або робота з XML.

- Пакет `email` — це бібліотека для керування повідомленнями електронної пошти, включаючи MIME та інші документи повідомлень на основі RFC 2822. На відміну від `smtplib` і `poplib`, які фактично надсилають і отримують повідомлення, пакет електронної пошти має повний набір інструментів для побудови або декодування складних структур повідомлень (включно з вкладеннями) і для реалізації інтернет-кодування та протоколів заголовків.

- Пакет `json` забезпечує надійну підтримку аналізу цього популярного формату обміну даними. Модуль `csv` підтримує пряме читання та запис файлів у форматі значень, розділених комами, який зазвичай підтримується базами даних і електронними таблицями. Обробка XML підтримується пакетами `xml.etree.ElementTree`, `xml.dom` і `xml.sax`. Разом ці модулі та пакети значно спрощують обмін даними між програмами Python та іншими інструментами.

- Модуль `sqlite3` — це оболонка для бібліотеки бази даних SQLite, яка забезпечує постійну базу даних, яку можна оновлювати та отримати до якої можна отримати доступ за допомогою дещо нестандартного синтаксису SQL.

- Інтернаціоналізація підтримується кількома модулями, зокрема `gettext`, `locale` і пакетом `codecs`.