Документация Python неофициальный перевод

library.md

551 строк · 51.1 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.9/faq/library.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# [Часто задаваемые вопросы по библиотекам и расширениям](https://python-all.ru/3.9/faq/library.html#id1)89Содержание1011- [FAQ по библиотекам и расширениям](https://python-all.ru/3.9/faq/library.html#library-and-extension-faq)1213  - [Общие вопросы по библиотекам](https://python-all.ru/3.9/faq/library.html#general-library-questions)1415    - [Как найти модуль или приложение для выполнения задачи X?](https://python-all.ru/3.9/faq/library.html#how-do-i-find-a-module-or-application-to-perform-task-x)16    - [Где находится исходный файл math.py (socket.py, regex.py и т.д.)?](https://python-all.ru/3.9/faq/library.html#where-is-the-math-py-socket-py-regex-py-etc-source-file)17    - [Как сделать скрипт Python исполняемым в Unix?](https://python-all.ru/3.9/faq/library.html#how-do-i-make-a-python-script-executable-on-unix)18    - [Существует ли пакет curses/termcap для Python?](https://python-all.ru/3.9/faq/library.html#is-there-a-curses-termcap-package-for-python)19    - [Есть ли в Python эквивалент onexit() из C?](https://python-all.ru/3.9/faq/library.html#is-there-an-equivalent-to-c-s-onexit-in-python)20    - [Почему не работают мои обработчики сигналов?](https://python-all.ru/3.9/faq/library.html#why-don-t-my-signal-handlers-work)21  - [Типовые задачи](https://python-all.ru/3.9/faq/library.html#common-tasks)2223    - [Как протестировать программу или компонент Python?](https://python-all.ru/3.9/faq/library.html#how-do-i-test-a-python-program-or-component)24    - [Как создать документацию из строк документации?](https://python-all.ru/3.9/faq/library.html#how-do-i-create-documentation-from-doc-strings)25    - [Как получить одиночное нажатие клавиши?](https://python-all.ru/3.9/faq/library.html#how-do-i-get-a-single-keypress-at-a-time)26  - [Потоки](https://python-all.ru/3.9/faq/library.html#threads)2728    - [Как программировать с использованием потоков?](https://python-all.ru/3.9/faq/library.html#how-do-i-program-using-threads)29    - [Ни один из моих потоков не запускается: почему?](https://python-all.ru/3.9/faq/library.html#none-of-my-threads-seem-to-run-why)30    - [Как распределить работу между несколькими рабочими потоками?](https://python-all.ru/3.9/faq/library.html#how-do-i-parcel-out-work-among-a-bunch-of-worker-threads)31    - [Какие виды изменения глобальных значений являются потокобезопасными?](https://python-all.ru/3.9/faq/library.html#what-kinds-of-global-value-mutation-are-thread-safe)32    - [Нельзя ли избавиться от глобальной блокировки интерпретатора (GIL)?](https://python-all.ru/3.9/faq/library.html#can-t-we-get-rid-of-the-global-interpreter-lock)33  - [Ввод и вывод](https://python-all.ru/3.9/faq/library.html#input-and-output)3435    - [Как удалить файл? (И другие вопросы о файлах…)](https://python-all.ru/3.9/faq/library.html#how-do-i-delete-a-file-and-other-file-questions)36    - [Как скопировать файл?](https://python-all.ru/3.9/faq/library.html#how-do-i-copy-a-file)37    - [Как читать (или записывать) двоичные данные?](https://python-all.ru/3.9/faq/library.html#how-do-i-read-or-write-binary-data)38    - [Не удаётся использовать os.read() на канале, созданном с помощью os.popen(); почему?](https://python-all.ru/3.9/faq/library.html#i-can-t-seem-to-use-os-read-on-a-pipe-created-with-os-popen-why)39    - [Как получить доступ к последовательному порту (RS232)?](https://python-all.ru/3.9/faq/library.html#how-do-i-access-the-serial-rs232-port)40    - [Почему закрытие sys.stdout (stdin, stderr) на самом деле не закрывает его?](https://python-all.ru/3.9/faq/library.html#why-doesn-t-closing-sys-stdout-stdin-stderr-really-close-it)41  - [Сетевое и интернет-программирование](https://python-all.ru/3.9/faq/library.html#network-internet-programming)4243    - [Какие существуют инструменты для работы с WWW в Python?](https://python-all.ru/3.9/faq/library.html#what-www-tools-are-there-for-python)44    - [Как имитировать отправку CGI-формы (METHOD=POST)?](https://python-all.ru/3.9/faq/library.html#how-can-i-mimic-cgi-form-submission-method-post)45    - [Какой модуль использовать для генерации HTML?](https://python-all.ru/3.9/faq/library.html#what-module-should-i-use-to-help-with-generating-html)46    - [Как отправить письмо из скрипта Python?](https://python-all.ru/3.9/faq/library.html#how-do-i-send-mail-from-a-python-script)47    - [Как избежать блокировки в методе connect() сокета?](https://python-all.ru/3.9/faq/library.html#how-do-i-avoid-blocking-in-the-connect-method-of-a-socket)48  - [Базы данных](https://python-all.ru/3.9/faq/library.html#databases)4950    - [Существуют ли интерфейсы к пакетам баз данных в Python?](https://python-all.ru/3.9/faq/library.html#are-there-any-interfaces-to-database-packages-in-python)51    - [Как реализовать постоянные объекты в Python?](https://python-all.ru/3.9/faq/library.html#how-do-you-implement-persistent-objects-in-python)52  - [Математика и численные методы](https://python-all.ru/3.9/faq/library.html#mathematics-and-numerics)5354    - [Как генерировать случайные числа в Python?](https://python-all.ru/3.9/faq/library.html#how-do-i-generate-random-numbers-in-python)5556## [Общие вопросы по библиотекам](https://python-all.ru/3.9/faq/library.html#id2)5758### [Как найти модуль или приложение для выполнения задачи X?](https://python-all.ru/3.9/faq/library.html#id3)5960Проверьте [справочник библиотеки](https://python-all.ru/3.9/library/index.html#library-index), чтобы узнать, есть ли подходящий модуль в стандартной библиотеке. (Со временем вы запомните, что входит в стандартную библиотеку, и сможете пропустить этот шаг.)6162Для сторонних пакетов выполните поиск в [Python Package Index](https://python-all.ru/3.9/faq/library.html) или воспользуйтесь [Google](https://python-all.ru/3.9/faq/library.html) или другой поисковой системой. Обычно поиск по «Python» с одним-двумя ключевыми словами по вашей теме находит что-нибудь полезное.6364### [Где находится исходный файл math.py (socket.py, regex.py и т. д.)?](https://python-all.ru/3.9/faq/library.html#id4)6566Если не удаётся найти исходный файл модуля, возможно, он встроенный или динамически загружаемый модуль, реализованный на C, C++ или другом компилируемом языке. В этом случае исходного файла может не быть, или он находится, например, в `mathmodule.c`, где-то в каталоге с исходниками на C (не на Python Path).6768В Python существует (как минимум) три вида модулей:69701. модули, написанные на Python (.py);712. модули, написанные на C и динамически загружаемые (.dll, .pyd, .so, .sl и т. д.);723. модули, написанные на C и связанные с интерпретатором; чтобы получить их список, введите:7374   ```python75   import sys76   print(sys.builtin_module_names)77   ```7879### [Как сделать скрипт Python исполняемым в Unix?](https://python-all.ru/3.9/faq/library.html#id5)8081Нужно сделать две вещи: установить исполняемый режим для файла скрипта и убедиться, что первая строка начинается с `#!`, за которым следует путь к интерпретатору Python.8283Первое выполняется командой `chmod +x scriptfile` или, возможно, `chmod 755 scriptfile`.8485Второе можно сделать несколькими способами. Самый простой – написать8687```python88#!/usr/local/bin/python89```9091в самой первой строке файла, указав путь к установленному на вашей платформе интерпретатору Python.9293Если вы хотите, чтобы скрипт не зависел от расположения интерпретатора Python, используйте программу **env**. Почти все варианты Unix поддерживают следующее, при условии, что интерпретатор Python находится в каталоге, входящем в `PATH` пользователя:9495```python96#!/usr/bin/env python97```9899*Не* делайте этого для CGI-скриптов. Переменная `PATH` для CGI-скриптов часто очень ограничена, поэтому нужно указывать полный абсолютный путь к интерпретатору.100101Иногда окружение пользователя настолько переполнено, что программа **/usr/bin/env** завершается с ошибкой; или программы env вообще нет. В таком случае можно попробовать следующий трюк (благодаря Алексу Резински):102103```sh104#! /bin/sh105""":"106exec python $0 ${1+"$@"}107"""108```109110Небольшой недостаток в том, что при этом определяется строка документации \_\_doc\_\_ скрипта. Однако это можно исправить, добавив111112```python113__doc__ = """...Whatever..."""114```115116### [Существует ли пакет curses/termcap для Python?](https://python-all.ru/3.9/faq/library.html#id6)117118Для вариантов Unix: стандартный дистрибутив исходного кода Python поставляется с модулем curses в подкаталоге [Modules](https://python-all.ru/3.9/faq/library.html), хотя по умолчанию он не компилируется. (Обратите внимание, что в дистрибутиве Windows его нет – модуля curses для Windows не существует.)119120Модуль [`curses`](https://python-all.ru/3.9/library/curses.html#module-curses) поддерживает базовые возможности curses, а также многие дополнительные функции из ncurses и SYSV curses, такие как цвет, поддержка альтернативных наборов символов, подокна и поддержка мыши. Это означает, что модуль несовместим с операционными системами, где есть только BSD curses, но сейчас, похоже, нет поддерживаемых ОС, попадающих в эту категорию.121122### [Есть ли в Python аналог onexit() из C?](https://python-all.ru/3.9/faq/library.html#id7)123124Модуль [`atexit`](https://python-all.ru/3.9/library/atexit.html#module-atexit) предоставляет функцию register, похожую на `onexit()` из C.125126### [Почему не работают мои обработчики сигналов?](https://python-all.ru/3.9/faq/library.html#id8)127128Самая распространённая проблема – обработчик сигнала объявлен с неправильным списком аргументов. Он вызывается как129130```python131handler(signum, frame)132```133134поэтому его следует объявлять с двумя параметрами:135136```python137def handler(signum, frame):138    ...139```140141## [Типовые задачи](https://python-all.ru/3.9/faq/library.html#id9)142143### [Как тестировать программу или компонент Python?](https://python-all.ru/3.9/faq/library.html#id10)144145В состав Python входят две тестовые платформы. Модуль [`doctest`](https://python-all.ru/3.9/library/doctest.html#module-doctest) находит примеры в строках документации модуля и запускает их, сравнивая вывод с ожидаемым выводом, указанным в строке документации.146147Модуль [`unittest`](https://python-all.ru/3.9/library/unittest.html#module-unittest) – это более продвинутая тестовая платформа, созданная по образцу тестовых платформ Java и Smalltalk.148149Чтобы упростить тестирование, используйте в программе хорошую модульную архитектуру. Почти вся функциональность должна быть инкапсулирована в функции или методы классов – и это иногда неожиданно и приятно ускоряет работу программы (потому что доступ к локальным переменным быстрее, чем к глобальным). Кроме того, программа не должна зависеть от изменения глобальных переменных, поскольку это сильно усложняет тестирование.150151«Глобальная основная логика» вашей программы может быть такой же простой, как152153```python154if __name__ == "__main__":155    main_logic()156```157158в конце главного модуля программы.159160Когда программа организована как удобная совокупность функций и классов, следует написать тестовые функции, проверяющие их поведение. Набор тестов, автоматизирующий последовательность проверок, можно связать с каждым модулем. Это кажется большой работой, но благодаря лаконичности и гибкости Python это на удивление легко. Можно сделать написание кода гораздо приятнее и увлекательнее, если писать тестовые функции параллельно с «рабочим кодом», так как это позволяет раньше находить ошибки и даже конструктивные недочёты.161162«Вспомогательные модули», не предназначенные для роли главного модуля программы, могут включать самопроверку модуля.163164```python165if __name__ == "__main__":166    self_test()167```168169Даже программы, взаимодействующие со сложными внешними интерфейсами, могут быть протестированы в отсутствие этих интерфейсов с помощью «фиктивных» интерфейсов, реализованных на Python.170171### [Как создавать документацию из строк документации?](https://python-all.ru/3.9/faq/library.html#id11)172173Модуль [`pydoc`](https://python-all.ru/3.9/library/pydoc.html#module-pydoc) может создавать HTML из строк документации в исходном коде Python. Альтернативой для создания API-документации исключительно по docstrings является [epydoc](https://python-all.ru/3.9/faq/library.html). [Sphinx](https://python-all.ru/3.9/faq/library.html) также может включать содержимое docstring.174175### [Как получить нажатие одной клавиши за раз?](https://python-all.ru/3.9/faq/library.html#id12)176177Для Unix-подобных систем есть несколько решений. Это несложно сделать с помощью curses, но curses – довольно большой модуль для изучения.178179## [Потоки](https://python-all.ru/3.9/faq/library.html#id13)180181### [Как программировать с помощью потоков?](https://python-all.ru/3.9/faq/library.html#id14)182183Обязательно используйте модуль [`threading`](https://python-all.ru/3.9/library/threading.html#module-threading), а не модуль [`_thread`](https://python-all.ru/3.9/library/_thread.html#module-_thread). Модуль [`threading`](https://python-all.ru/3.9/library/threading.html#module-threading) создаёт удобные абстракции поверх низкоуровневых примитивов, предоставляемых модулем [`_thread`](https://python-all.ru/3.9/library/_thread.html#module-_thread).184185### [Почему ни один из моих потоков не выполняется?](https://python-all.ru/3.9/faq/library.html#id15)186187Как только главный поток завершается, все потоки уничтожаются. Главный поток выполняется слишком быстро, не давая потокам времени на работу.188189Простое исправление – добавить в конец программы задержку, достаточно длинную для завершения всех потоков:190191```python192import threading, time193194def thread_task(name, n):195    for i in range(n):196        print(name, i)197198for i in range(10):199    T = threading.Thread(target=thread_task, args=(str(i), i))200    T.start()201202time.sleep(10)  # <---------------------------!203```204205Но теперь (на многих платформах) потоки не выполняются параллельно, а, похоже, выполняются последовательно, один за другим! Причина в том, что планировщик потоков ОС не запускает новый поток, пока предыдущий не заблокирован.206207Простое исправление – добавить небольшую задержку в начало функции run:208209```python210def thread_task(name, n):211    time.sleep(0.001)  # <--------------------!212    for i in range(n):213        print(name, i)214215for i in range(10):216    T = threading.Thread(target=thread_task, args=(str(i), i))217    T.start()218219time.sleep(10)220```221222Вместо попыток угадать подходящее значение задержки для [`time.sleep()`](https://python-all.ru/3.9/library/time.html#time.sleep) лучше использовать какой-нибудь семафорный механизм. Одна из идей – использовать модуль [`queue`](https://python-all.ru/3.9/library/queue.html#module-queue) для создания объекта очереди, позволить каждому потоку добавлять токен в очередь по завершении, а главному потоку – читать из очереди столько токенов, сколько потоков.223224### [Как распределить работу между несколькими рабочими потоками?](https://python-all.ru/3.9/faq/library.html#id16)225226Самый простой способ – использовать модуль [`concurrent.futures`](https://python-all.ru/3.9/library/concurrent.futures.html#module-concurrent.futures), особенно класс [`ThreadPoolExecutor`](https://python-all.ru/3.9/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor).227228Или, если требуется тонкий контроль над алгоритмом распределения, можно написать собственную логику вручную. Используйте модуль [`queue`](https://python-all.ru/3.9/library/queue.html#module-queue) для создания очереди со списком заданий. Класс [`Queue`](https://python-all.ru/3.9/library/queue.html#queue.Queue) поддерживает список объектов и имеет метод `.put(obj)`, добавляющий элементы в очередь, и метод `.get()`, возвращающий их. Класс позаботится о блокировках, необходимых, чтобы каждое задание было выдано ровно один раз.229230Вот простой пример:231232```python233import threading, queue, time234235# Рабочий поток забирает задания из очереди. Когда очередь пуста, он236# предполагает, что больше работы не будет, и завершается.237# (На практике рабочие потоки работают до принудительного завершения.)238def worker():239    print('Running worker')240    time.sleep(0.1)241    while True:242        try:243            arg = q.get(block=False)244        except queue.Empty:245            print('Worker', threading.currentThread(), end=' ')246            print('queue empty')247            break248        else:249            print('Worker', threading.currentThread(), end=' ')250            print('running with argument', arg)251            time.sleep(0.5)252253# Создать очередь254q = queue.Queue()255256# Запустить пул из 5 рабочих потоков257for i in range(5):258    t = threading.Thread(target=worker, name='worker %i' % (i+1))259    t.start()260261# Начать добавление заданий в очередь262for i in range(50):263    q.put(i)264265# Дать потокам время на выполнение266print('Main thread sleeping')267time.sleep(5)268```269270При запуске это выдаст следующий вывод:271272```text273Running worker274Running worker275Running worker276Running worker277Running worker278Main thread sleeping279Worker <Thread(worker 1, started 130283832797456)> running with argument 0280Worker <Thread(worker 2, started 130283824404752)> running with argument 1281Worker <Thread(worker 3, started 130283816012048)> running with argument 2282Worker <Thread(worker 4, started 130283807619344)> running with argument 3283Worker <Thread(worker 5, started 130283799226640)> running with argument 4284Worker <Thread(worker 1, started 130283832797456)> running with argument 5285...286```287288Обратитесь к документации модуля за подробностями; класс [`Queue`](https://python-all.ru/3.9/library/queue.html#queue.Queue) предоставляет многофункциональный интерфейс.289290### [Какие виды изменения глобальных значений потокобезопасны?](https://python-all.ru/3.9/faq/library.html#id17)291292Внутренне используется [глобальная блокировка интерпретатора](https://python-all.ru/3.9/glossary.html#term-global-interpreter-lock) (GIL), чтобы гарантировать, что в виртуальной машине Python одновременно выполняется только один поток. В общем случае Python переключается между потоками только между инструкциями байткода; частота переключений задаётся через [`sys.setswitchinterval()`](https://python-all.ru/3.9/library/sys.html#sys.setswitchinterval). Таким образом, каждая инструкция байткода и, следовательно, весь реализованный на C код, вызываемый из этой инструкции, атомарны с точки зрения программы на Python.293294Теоретически это означает, что точный учёт требует точного понимания реализации байткода виртуальной машины Python. На практике это означает, что операции над совместно используемыми переменными встроенных типов (int, list, dict и т.д.), которые «выглядят атомарными», действительно атомарны.295296Например, следующие операции атомарны (L, L1, L2 – списки, D, D1, D2 – словари, x, y – объекты, i, j – целые числа):297298```python299L.append(x)300L1.extend(L2)301x = L[i]302x = L.pop()303L1[i:j] = L2304L.sort()305x = y306x.field = y307D[x] = y308D1.update(D2)309D.keys()310```311312А эти – нет:313314```python315i = i+1316L.append(L[-1])317L[i] = L[j]318D[x] = D[x] + 1319```320321Операции, заменяющие другие объекты, могут вызывать метод [`__del__()`](https://python-all.ru/3.9/reference/datamodel.html#object.__del__) этих объектов, когда счётчик ссылок достигает нуля, и это может повлиять на другие вещи. Особенно это касается массовых обновлений словарей и списков. Если есть сомнения, используйте мьютекс!322323### [Нельзя ли избавиться от глобальной блокировки интерпретатора?](https://python-all.ru/3.9/faq/library.html#id18)324325[Глобальная блокировка интерпретатора](https://python-all.ru/3.9/glossary.html#term-global-interpreter-lock) (GIL) часто считается помехой для развёртывания Python на высокопроизводительных многопроцессорных серверных машинах, поскольку многопоточная программа на Python фактически использует только один процессор из-за требования, что (почти) весь код Python может выполняться только при удерживаемом GIL.326327Во времена Python 1.5 Грег Стайн реализовал обширный набор патчей (так называемые «free threading» патчи), который удалял GIL и заменял его более мелкозернистой блокировкой. Недавно Адам Олсен провёл похожий эксперимент в своём проекте [python-safethread](https://python-all.ru/3.9/faq/library.html). К сожалению, оба эксперимента продемонстрировали резкое падение производительности в однопоточном режиме (как минимум на 30%), из-за большого количества мелкозернистых блокировок, необходимых для компенсации удаления GIL.328329Это не значит, что Python нельзя эффективно использовать на многопроцессорных машинах! Просто нужно подойти творчески и разделять работу между несколькими *процессами*, а не несколькими *потоками*. Класс [`ProcessPoolExecutor`](https://python-all.ru/3.9/library/concurrent.futures.html#concurrent.futures.ProcessPoolExecutor) из нового модуля [`concurrent.futures`](https://python-all.ru/3.9/library/concurrent.futures.html#module-concurrent.futures) предоставляет простой способ сделать это; модуль [`multiprocessing`](https://python-all.ru/3.9/library/multiprocessing.html#module-multiprocessing) предоставляет API более низкого уровня, если требуется более тонкий контроль над распределением задач.330331Разумное использование расширений на C также может помочь; если используется расширение на C для выполнения трудоёмкой задачи, оно может освободить GIL, пока поток выполнения находится в C-коде, и позволить другим потокам выполнять работу. Некоторые модули стандартной библиотеки, такие как [`zlib`](https://python-all.ru/3.9/library/zlib.html#module-zlib) и [`hashlib`](https://python-all.ru/3.9/library/hashlib.html#module-hashlib), уже так делают.332333Высказывались предложения сделать GIL блокировкой на уровне состояния интерпретатора, а не глобальной; тогда интерпретаторы не смогли бы обмениваться объектами. К сожалению, это тоже вряд ли произойдёт. Это потребовало бы огромного объёма работы, поскольку многие реализации объектов в настоящее время используют глобальное состояние. Например, небольшие целые числа и короткие строки кэшируются; эти кэши пришлось бы перенести в состояние интерпретатора. Другие типы объектов имеют свои собственные списки свободной памяти; эти списки также пришлось бы перенести. И так далее.334335И я сомневаюсь, что это вообще можно сделать за конечное время, потому что та же проблема существует и для сторонних расширений. Скорее всего, сторонние расширения пишутся быстрее, чем вы успеваете переделывать их для хранения всего глобального состояния в состоянии интерпретатора.336337И наконец, если у вас есть несколько интерпретаторов, не разделяющих состояние, что вы выигрываете по сравнению с запуском каждого интерпретатора в отдельном процессе?338339## [Ввод и вывод](https://python-all.ru/3.9/faq/library.html#id19)340341### [Как удалить файл? (И другие вопросы о файлах…)](https://python-all.ru/3.9/faq/library.html#id20)342343Используйте `os.remove(filename)` или `os.unlink(filename)`; документацию смотрите в модуле [`os`](https://python-all.ru/3.9/library/os.html#module-os). Эти две функции идентичны; [`unlink()`](https://python-all.ru/3.9/library/os.html#os.unlink) – просто имя системного вызова Unix для этой функции.344345Чтобы удалить каталог, используйте [`os.rmdir()`](https://python-all.ru/3.9/library/os.html#os.rmdir); для создания используйте [`os.mkdir()`](https://python-all.ru/3.9/library/os.html#os.mkdir). `os.makedirs(path)` создаст все промежуточные каталоги в `path`, которые не существуют. `os.removedirs(path)` удалит промежуточные каталоги, если они пусты; если нужно удалить всё дерево каталогов и его содержимое, используйте [`shutil.rmtree()`](https://python-all.ru/3.9/library/shutil.html#shutil.rmtree).346347Чтобы переименовать файл, используйте `os.rename(old_path, new_path)`.348349Чтобы урезать файл, откройте его с помощью `f = open(filename, "rb+")` и используйте `f.truncate(offset)`; смещение по умолчанию равно текущей позиции. Также есть `os.ftruncate(fd, offset)` для файлов, открытых с помощью [`os.open()`](https://python-all.ru/3.9/library/os.html#os.open), где *fd* – это файловый дескриптор (небольшое целое число).350351Модуль [`shutil`](https://python-all.ru/3.9/library/shutil.html#module-shutil) также содержит ряд функций для работы с файлами, включая [`copyfile()`](https://python-all.ru/3.9/library/shutil.html#shutil.copyfile), [`copytree()`](https://python-all.ru/3.9/library/shutil.html#shutil.copytree) и [`rmtree()`](https://python-all.ru/3.9/library/shutil.html#shutil.rmtree).352353### [Как скопировать файл?](https://python-all.ru/3.9/faq/library.html#id21)354355Модуль [`shutil`](https://python-all.ru/3.9/library/shutil.html#module-shutil) содержит функцию [`copyfile()`](https://python-all.ru/3.9/library/shutil.html#shutil.copyfile). Обратите внимание, что на MacOS 9 она не копирует вилку ресурсов и информацию Finder.356357### [Как читать (или записывать) двоичные данные?](https://python-all.ru/3.9/faq/library.html#id22)358359Для чтения или записи сложных двоичных форматов данных лучше всего использовать модуль [`struct`](https://python-all.ru/3.9/library/struct.html#module-struct). Он позволяет взять строку, содержащую двоичные данные (обычно числа), и преобразовать её в объекты Python; и наоборот.360361Например, следующий код читает из файла два 2-байтовых целых числа и одно 4-байтовое целое число в формате big-endian:362363```python364import struct365366with open(filename, "rb") as f:367    s = f.read(8)368    x, y, z = struct.unpack(">hhl", s)369```370371Символ ‘\>’ в строке формата указывает на порядок байтов big-endian; буква ‘h’ читает одно «короткое целое» (2 байта), а ‘l’ – одно «длинное целое» (4 байта) из строки.372373Для данных, которые являются более регулярными (например, однородный список целых или чисел с плавающей запятой), можно также использовать модуль [`array`](https://python-all.ru/3.9/library/array.html#module-array).374375> **Примечание**376>377> Для чтения и записи двоичных данных необходимо открыть файл в двоичном режиме (здесь передаётся `"rb"` в [`open()`](https://python-all.ru/3.9/library/functions.html#open)). Если вместо этого используется `"r"` (по умолчанию), файл будет открыт в текстовом режиме, и `f.read()` будет возвращать объекты [`str`](https://python-all.ru/3.9/library/stdtypes.html#str), а не [`bytes`](https://python-all.ru/3.9/library/stdtypes.html#bytes).378379### [Не удаётся использовать os.read() для канала, созданного с помощью os.popen(); почему?](https://python-all.ru/3.9/faq/library.html#id23)380381[`os.read()`](https://python-all.ru/3.9/library/os.html#os.read) – это низкоуровневая функция, которая принимает файловый дескриптор – небольшое целое число, представляющее открытый файл. [`os.popen()`](https://python-all.ru/3.9/library/os.html#os.popen) создаёт высокоуровневый файловый объект того же типа, что возвращается встроенной функцией [`open()`](https://python-all.ru/3.9/library/functions.html#open). Таким образом, чтобы прочитать *n* байт из канала *p*, созданного с помощью [`os.popen()`](https://python-all.ru/3.9/library/os.html#os.popen), нужно использовать `p.read(n)`.382383### [Как получить доступ к последовательному порту (RS232)?](https://python-all.ru/3.9/faq/library.html#id24)384385Для Win32, OSX, Linux, BSD, Jython, IronPython:386387> [https://pypi.org/project/pyserial/](https://python-all.ru/3.9/faq/library.html)388389Для Unix смотрите сообщение в Usenet от Митча Чепмена:390391> [https://groups.google.com/groups?selm=34A04430.CF9@ohioee.com](https://python-all.ru/3.9/faq/library.html)392393### [Почему закрытие sys.stdout (stdin, stderr) на самом деле не закрывает его?](https://python-all.ru/3.9/faq/library.html#id25)394395Python [file objects](https://python-all.ru/3.9/glossary.html#term-file-object) are a high-level layer of abstraction on low-level C file descriptors.396397Для большинства файловых объектов, создаваемых в Python через встроенную функцию [`open()`](https://python-all.ru/3.9/library/functions.html#open), `f.close()` помечает файловый объект Python как закрытый с точки зрения Python, а также организует закрытие нижележащего файлового дескриптора C. Это также происходит автоматически в деструкторе `f`, когда `f` становится мусором.398399Но stdin, stdout и stderr обрабатываются Python особым образом из-за особого статуса, присвоенного им также в C. Вызов `sys.stdout.close()` помечает файловый объект на уровне Python как закрытый, но *не* закрывает связанный файловый дескриптор C.400401Чтобы закрыть нижележащий файловый дескриптор C для одного из этих трёх, сначала следует убедиться, что это действительно нужно сделать (например, можно запутать модули расширений, пытающиеся выполнять ввод-вывод). Если это так, используйте [`os.close()`](https://python-all.ru/3.9/library/os.html#os.close):402403```python404os.close(stdin.fileno())405os.close(stdout.fileno())406os.close(stderr.fileno())407```408409Или можно использовать числовые константы 0, 1 и 2 соответственно.410411## [Сетевое и интернет-программирование](https://python-all.ru/3.9/faq/library.html#id26)412413### [Какие WWW-инструменты есть для Python?](https://python-all.ru/3.9/faq/library.html#id27)414415Смотрите главы [Интернет-протоколы и поддержка](https://python-all.ru/3.9/library/internet.html#internet) и [Обработка интернет-данных](https://python-all.ru/3.9/library/netdata.html#netdata) в Справочном руководстве по библиотеке Python. В Python есть много модулей, которые помогут создать веб-системы как на стороне сервера, так и на стороне клиента.416417Сводка доступных фреймворков поддерживается Полом Бодди на\\n[https://wiki.python.org/moin/WebProgramming](https://python-all.ru/3.9/faq/library.html).418419Кэмерон Лэрд поддерживает полезный набор страниц о веб-технологиях Python по адресу [http://phaseit.net/claird/comp.lang.python/web\_python](https://python-all.ru/3.9/faq/library.html).420421### [Как имитировать отправку CGI-формы (METHOD=POST)?](https://python-all.ru/3.9/faq/library.html#id28)422423Мне нужно получать веб-страницы, которые появляются после отправки формы. Существует ли готовый код, позволяющий это сделать?424425Да. Вот простой пример использования [`urllib.request`](https://python-all.ru/3.9/library/urllib.request.html#module-urllib.request):426427```python428#!/usr/local/bin/python429430import urllib.request431432# сформировать строку запроса433qs = "First=Josephine&MI=Q&Last=Public"434435# подключиться и отправить серверу путь436req = urllib.request.urlopen('http://www.some-server.out-there'437                             '/cgi-bin/some-cgi-script', data=qs)438with req:439    msg, hdrs = req.read(), req.info()440```441442Обратите внимание, что в целом для POST-операций с процентным кодированием строки запроса должны быть экранированы с помощью [`urllib.parse.urlencode()`](https://python-all.ru/3.9/library/urllib.parse.html#urllib.parse.urlencode). Например, чтобы отправить `name=Guy Steele, Jr.`:443444```python445>>> import urllib.parse446>>> urllib.parse.urlencode({'name': 'Guy Steele, Jr.'})447'name=Guy+Steele%2C+Jr.'448```449450> **См. также**451>452> [Руководство по получению интернет-ресурсов с помощью пакета urllib](https://python-all.ru/3.9/howto/urllib2.html#urllib-howto) с многочисленными примерами.453454### [Какой модуль использовать для генерации HTML?](https://python-all.ru/3.9/faq/library.html#id29)455456Вы можете найти подборку полезных ссылок на [вики-странице Web Programming](https://python-all.ru/3.9/faq/library.html).457458### [Как отправить письмо из скрипта Python?](https://python-all.ru/3.9/faq/library.html#id30)459460Используйте модуль стандартной библиотеки [`smtplib`](https://python-all.ru/3.9/library/smtplib.html#module-smtplib).461462Вот очень простой интерактивный отправитель почты, использующий этот модуль. Этот метод будет\\nработать на любом хосте, поддерживающем SMTP-слушатель.463464```python465import sys, smtplib466467fromaddr = input("From: ")468toaddrs  = input("To: ").split(',')469print("Enter message, end with ^D:")470msg = ''471while True:472    line = sys.stdin.readline()473    if not line:474        break475    msg += line476477# Непосредственная отправка письма478server = smtplib.SMTP('localhost')479server.sendmail(fromaddr, toaddrs, msg)480server.quit()481```482483Альтернатива, доступная только в Unix, использует sendmail. Расположение программы sendmail различается в разных системах: иногда это `/usr/lib/sendmail`, иногда\\n`/usr/sbin/sendmail`. Страница руководства sendmail поможет разобраться. Вот пример кода:484485```python486import os487488SENDMAIL = "/usr/sbin/sendmail"  # Расположение sendmail489p = os.popen("%s -t -i" % SENDMAIL, "w")490p.write("To: receiver@example.com\n")491p.write("Subject: test\n")492p.write("\n")  # Пустая строка, отделяющая заголовки от тела493p.write("Some text\n")494p.write("some more text\n")495sts = p.close()496if sts != 0:497    print("Sendmail exit status", sts)498```499500### [Как избежать блокировки в методе connect() сокета?](https://python-all.ru/3.9/faq/library.html#id31)501502Модуль [`select`](https://python-all.ru/3.9/library/select.html#module-select) обычно используется для асинхронного ввода-вывода на сокетах.503504Чтобы предотвратить блокировку при TCP-подключении, можно перевести сокет в неблокирующий режим. Затем при вызове `socket.connect()` соединение либо установится сразу (маловероятно), либо будет получено исключение, содержащее номер ошибки в `.errno`. `errno.EINPROGRESS` означает, что соединение устанавливается, но ещё не завершено. В разных ОС возвращаются разные значения, поэтому потребуется проверить, что возвращается в вашей системе.505506Можно использовать метод `socket.connect_ex()`, чтобы избежать создания исключения. Он просто вернёт значение errno. Для опроса можно вызвать `socket.connect_ex()` повторно позже – `0` или `errno.EISCONN` означают, что соединение установлено – или передать этот сокет в [`select.select()`](https://python-all.ru/3.9/library/select.html#select.select), чтобы проверить, доступен ли он для записи.507508> **Примечание**509>510> Модуль [`asyncio`](https://python-all.ru/3.9/library/asyncio.html#module-asyncio) предоставляет универсальную однопоточную и конкурентную асинхронную библиотеку, которую можно использовать для написания неблокирующего сетевого кода. Сторонняя библиотека [Twisted](https://python-all.ru/3.9/faq/library.html) является популярной и многофункциональной альтернативой.511512## [Базы данных](https://python-all.ru/3.9/faq/library.html#id32)513514### [Существуют ли интерфейсы к пакетам баз данных в Python?](https://python-all.ru/3.9/faq/library.html#id33)515516Да.517518Интерфейсы к дисковым хешам, таким как [`DBM`](https://python-all.ru/3.9/library/dbm.html#module-dbm.ndbm) и [`GDBM`](https://python-all.ru/3.9/library/dbm.html#module-dbm.gnu), также включены в стандартный Python. Также есть модуль [`sqlite3`](https://python-all.ru/3.9/library/sqlite3.html#module-sqlite3), предоставляющий лёгкую дисковую реляционную базу данных.519520Доступна поддержка большинства реляционных баз данных. Подробнее см. на [вики-странице DatabaseProgramming](https://python-all.ru/3.9/faq/library.html).521522### [Как реализовать постоянные объекты в Python?](https://python-all.ru/3.9/faq/library.html#id34)523524Модуль библиотеки [`pickle`](https://python-all.ru/3.9/library/pickle.html#module-pickle) решает эту задачу очень общим способом (хотя\\nвсё ещё нельзя хранить такие вещи, как открытые файлы, сокеты или окна), а модуль [`shelve`](https://python-all.ru/3.9/library/shelve.html#module-shelve) использует pickle и (g)dbm для создания постоянных отображений, содержащих произвольные объекты Python.525526## [Математика и численные методы](https://python-all.ru/3.9/faq/library.html#id35)527528### [Как генерировать случайные числа в Python?](https://python-all.ru/3.9/faq/library.html#id36)529530Стандартный модуль [`random`](https://python-all.ru/3.9/library/random.html#module-random) реализует генератор случайных чисел. Использовать его просто:531532```python533import random534random.random()535```536537Возвращает случайное число с плавающей запятой в диапазоне \[0, 1).538539В этом модуле также есть много других специализированных генераторов, например:540541- `randrange(a, b)` выбирает целое число в диапазоне \[a, b).542- `uniform(a, b)` выбирает число с плавающей запятой в диапазоне \[a, b).543- `normalvariate(mean, sdev)` делает выборку из нормального (гауссова) распределения.544545Некоторые функции более высокого уровня работают непосредственно с последовательностями, например:546547- `choice(S)` выбирает случайный элемент из заданной последовательности.548- `shuffle(L)` перемешивает список на месте, то есть переставляет его элементы случайным образом.549550Также существует класс `Random`, экземпляр которого можно создать для получения независимых генераторов случайных чисел.551